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
If Not IsPostBack Then
Dim dt As DataTable = New DataTable
Dim i As Integer
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
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
dt.Rows.Add(dr)
Next
Session("Source") = dt
Session.Timeout = 600
DataGrid1.DataSource = dt
DataBind()
DataGrid1.Columns(8).Visible = False
DataGrid1.ToolTip = "Click the header text" & _
" to set the column in edit mode"
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
Dim i, y As Integer
Dim dt As DataTable = New DataTable
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
For Each dgi In DataGrid1.Items
y = y + 1
dr = dt.NewRow()
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
DataGrid1.DataSource = dt
DataBind()
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 For
� Next
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
CreateDataSource()
Dim dt As DataTable = CType(Session("Source"), DataTable)
Dim ColumnNr As Integer
ColumnNr = dt.Columns(e.SortExpression).Ordinal
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:
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 TextBox
es and setting a new column in edit mode. And again I simply use the For
� Next
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.