Click here to Skip to main content
Click here to Skip to main content

How to set an entire DataGrid column to edit mode

, 17 Feb 2006 CPOL
Rate this:
Please Sign up or sign in to vote.
This article explains how to set an entire DataGrid column to edit mode.

Introduction

We all know the Insert, Edit, and Update columns available in a DataGrid. These commands are very useful if you don’t have too many rows and you want to edit an entire row.

But what if you want to just edit values in a column? A couple of days ago, that was my case. I wanted to edit an entire column, so I started looking for some code to solve the task. I could not find anything in the internet so I had to write some code myself.

View an online example here.

The Code

Let’s see how to do it. First, we have to find a way to tell which row we want to edit, and a good solution is to use the grid sort command like this, and I show you the rest a little later:

Private Sub ItemsGrid_SortCommand(ByVal source As System.Object, _
    ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) _
    Handles DataGrid1.SortCommand
End Sub

Second, we have to do some formatting to the DataGrid. In the property builder for the DataGrid, we add some bound columns. Fill in the header text and the data field for the columns, click to convert to template columns, and fill in the sort expression for each column that we want to edit. Finally, we set the AllowSorting property to True.

In the designer, right click the DataGrid and choose Edit Template, go through every column, and move the text box from EditItemTemplate to EditTemplate together with the Label control that is already there. We set the numbers of the Label controls and TextBox controls to match the numbers of the columns, to make the code easier in the code behind.

The HTML code for the grid in this example looks like this. Copy it between your <body></body> tags.

<form id="Form1" method="post" runat="server">
  <TABLE id="Table1" style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 24px" 
              cellSpacing="1" cellPadding="1" width="600" border="1">
      <tr>
        <TD>
          <asp:datagrid id="DataGrid1" runat="server" AllowSorting="True" 
              GridLines="Vertical" CellPadding="3" BackColor="White" 
              BorderWidth="1px" BorderColor="#999999" 
              AutoGenerateColumns="False" BorderStyle="None">
            <FooterStyle ForeColor="Black" BackColor="#CCCCCC"></FooterStyle>
            <SelectedItemStyle Font-Bold="True" ForeColor="White" 
                         BackColor="#008A8C"></SelectedItemStyle>
            <AlternatingItemStyle BackColor="Gainsboro"></AlternatingItemStyle>
            <ItemStyle ForeColor="Black" BackColor="#EEEEEE"></ItemStyle>
            <HeaderStyle Font-Bold="True" ForeColor="White" 
                         BackColor="#000084"></HeaderStyle>
            <Columns>
            <asp:BoundColumn DataField="IdNr" HeaderText="IdNr"></asp:BoundColumn>
              <asp:TemplateColumn SortExpression="Item1" HeaderText="Item1">
                <ItemTemplate>
                  <asp:Label id=Label1 runat="server" 
                     Text='<%# DataBinder.Eval(Container, "DataItem.Item1") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox1 runat="server" 
                     Text='<%# DataBinder.Eval(Container, "DataItem.Item1") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item2" HeaderText="Item2">
                <ItemTemplate>
                  <asp:Label id=Label2 runat="server" 
                     Text='<%# DataBinder.Eval(Container, "DataItem.Item2") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox2 runat="server" 
                     Text='<%# DataBinder.Eval(Container, "DataItem.Item2") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item3" HeaderText="Item3">
                <ItemTemplate>
                  <asp:Label id=Label3 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item3") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox3 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item3") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item4" HeaderText="Item4">
                <ItemTemplate>
                  <asp:Label id=Label4 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item4") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox4 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item4") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item5" HeaderText="Item5">
                <ItemTemplate>
                  <asp:Label id=Label5 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item5") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox5 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item5") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item6" HeaderText="Item6">
                <ItemTemplate>
                  <asp:Label id=Label6 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item6") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox6 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item6") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item7" HeaderText="Item7">
                <ItemTemplate>
                  <asp:Label id=Label7 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item7") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox7 runat="server" 
                         Text='<%# DataBinder.Eval(Container, "DataItem.Item7") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
              <asp:TemplateColumn SortExpression="Item8" HeaderText="Item8">
                <ItemTemplate>
                  <asp:Label id=Label8 runat="server" 
                           Text='<%# DataBinder.Eval(Container, "DataItem.Item8") %>'>
                  </asp:Label>
                  <asp:TextBox id=TextBox8 runat="server" 
                           Text='<%# DataBinder.Eval(Container, "DataItem.Item8") %>'>
                  </asp:TextBox>
                </ItemTemplate>
              </asp:TemplateColumn>
            </Columns>
            <PagerStyle HorizontalAlign="Center" ForeColor="Black" 
                  BackColor="#999999" Mode="NumericPages"></PagerStyle>
          </asp:datagrid>
        </TD>
      </tr>
  </TABLE>
</form>

Then we have to write some code, and first we have to populate the grid. Use this code:

Private Sub Page_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load
    'Put user code to initialize the page here
    If Not IsPostBack Then

        ' Populate the table the fist time the page is loaded.
        'Here you can use whatever source you want. Maybe a DataBase.
        Dim dt As DataTable = New DataTable
        Dim i As Integer

        ' Define the columns in the table.
        dt.Columns.Add(New DataColumn("IdNr", GetType(String)))
        For i = 1 To 9
            dt.Columns.Add(New DataColumn("Item" & i, _
                                      GetType(String)))
        Next

        Dim dr As DataRow

        'Adding some values to populate the table
        For i = 1 To 10
            dr = dt.NewRow()
            dr(0) = i & 1
            dr(1) = "Hello World " & i & 2
            dr(2) = "Hello World " & i & 3
            dr(3) = "Hello World " & i & 4
            dr(4) = "Hello World " & i & 5
            dr(5) = "Hello World " & i & 6
            dr(6) = "Hello World " & i & 7
            dr(7) = "Hello World " & i & 8
            dr(8) = "Hello World " & i & 9

            'Fill the table
            dt.Rows.Add(dr)
        Next

        ' Take care of the values between roundtrips to the server 
        Session("Source") = dt
        Session.Timeout = 600

        'Binding the values from the table to the grid and fill it.
        DataGrid1.DataSource = dt
        DataBind()

        DataGrid1.Columns(8).Visible = False
        DataGrid1.ToolTip = "Click the header text" & _ 
                  " to set the column in edit mode"

        'Hide all textBoxes in the grid
        Dim dgi As DataGridItem
        For i = 1 To DataGrid1.Columns.Count - 1
            For Each dgi In DataGrid1.Items
                CType(dgi.Cells(i).FindControl("TextBox"_
                         & i), TextBox).Visible = False
            Next
        Next

    End If
End Sub

Next, we want to preserve the edited values and all other values between the roundtrips to the server. Here we use a function and an ICollection like this:

Function CreateDataSource() As ICollection
    ' Create a new DataTable based on values from the DataGrid
    Dim i, y As Integer

    Dim dt As DataTable = New DataTable

    ' Filling in the same headers as in the existing DataGrid
    For i = 0 To DataGrid1.Columns.Count - 1
        dt.Columns.Add(New _
          DataColumn(DataGrid1.Columns(i).HeaderText, _
          GetType(String)))
    Next

    Dim dr As DataRow

    Dim dgi As DataGridItem
    'Fill in the vaues from the DataGrid including new entries
    For Each dgi In DataGrid1.Items
        ' Making a counter to track
        ' the row number for column 0
        ' that is not in edit mode.
        y = y + 1
        dr = dt.NewRow()

        'Duplicate the DataGrid
        dr(0) = DataGrid1.Items(y - 1).Cells(0).Text
        For i = 1 To DataGrid1.Columns.Count - 1
            dr(i) = _
              CType(dgi.Cells(i).FindControl("TextBox" _
              & i), TextBox).Text
        Next
        dt.Rows.Add(dr)
    Next

    'Bind the grid with the new values
    DataGrid1.DataSource = dt
    DataBind()


    ' Take care of the values between roundtrips to the server 
    Session("Source") = dt
    Session.Timeout = 600

End Function

Now, you see why we set the number of the Label and TextBox controls to match the column numbers and in increasing order. It makes it easy to use a ForNext loop.

There still is some code missing, and that is for how to set the columns in edit mode, and here it is:

Private Sub ItemsGrid_SortCommand(ByVal source As System.Object, _
        ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs) _
        Handles DataGrid1.SortCommand
    'Using the sort command to set the textBoxes in edit mode

    CreateDataSource() 'First calling Function to rebind the Grid

    'Find the column that was clicked
    Dim dt As DataTable = CType(Session("Source"), DataTable)
    Dim ColumnNr As Integer
    ColumnNr = dt.Columns(e.SortExpression).Ordinal

    'Hide the textBoxes and open a new column in edit mode
    Dim dgi As DataGridItem
    Dim i As Integer

    For Each dgi In DataGrid1.Items

        For i = 1 To DataGrid1.Columns.Count - 1
            CType(dgi.Cells(ColumnNr).FindControl("TextBox" _
                      & ColumnNr), TextBox).Visible = True
            CType(dgi.Cells(ColumnNr).FindControl("Label" & _
                       ColumnNr), Label).Visible = False
            CType(dgi.Cells(ColumnNr).FindControl("TextBox" _
                            & i), TextBox).Visible = False
        Next
    Next

End Sub

Here you see that I’m using a DataTable, and that is because I use it to find the column that was clicked. Like this:

'Find the column that was clicked
Dim dt As DataTable = CType(Session("Source"), DataTable)
Dim ColumnNr As Integer
ColumnNr = dt.Columns(e.SortExpression).Ordinal

The reason why I’m doing this is that .Ordinal is not a member of the DataGrid collection.

The rest is just hiding the TextBoxes and setting a new column in edit mode. And again I simply use the ForNext loop.

Another advantage of doing it this way is that during the process of editing, we are not posting anything back to the database. We can simply finish all the editing, and when finishing, we can send the edited grid back to the database. Just add an Update button and write some code to do this.

Hope this can be useful for someone.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Sigurd Johansen
Web Developer
Norway Norway
No Biography provided

Comments and Discussions

 
RantMy vote of 1 Pinmemberhiren0070013-Aug-10 0:57 
GeneralI need something like this, but with a checkbox Pinmemberpatanpatan14-Feb-07 11:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.1411023.1 | Last Updated 17 Feb 2006
Article Copyright 2006 by Sigurd Johansen
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid