Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to set an entire DataGrid column to edit mode

0.00/5 (No votes)
17 Feb 2006 1  
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here