
Introduction
This article will be very useful to all users who are working with ASP.NET 2.0 GridView
control. Here, I will explain how to work with the GridView
control in ASP.NET 2.0, which is very easier to use than the DataGrid
control in ASP.NET 1.1. I will also explain the differences between the GridView
and the DataGrid
controls. We will also look into how to work with a template column having a DataGrid
inside it.
Background
The basic idea behind this article is to see how much the ASP.NET 2.0's GridView
control is easier to work than the DataGrid
control in ASP.NET 1.1. I have previously worked with the DataGrid
control, and I know how difficult it is to work with it in the same project in which I am using the GridView
control. Working with the ASP.NET 2.0 GridView
control is very easy as it is very user friendly. Though I had faced a lot of difficulties in using it, I can still say it is far better than the DataGrid
control. The GridView
control gives you Edit, Update, Delete, Sorting, Selection, and Paging functionality built-in.
Using the code
Here in this project, I have used an ObjectDataSource
control for binding the GridView
to the data source. This is one of the best features available in VS.NET 2005. It is very easy to work with it.
The main difference between a DataGrid
and a GridView
control is that the DataGrid
control has centralized event handling which means any event raised by a control inside the DataGrid
’s template column will be handled by the ItemCommand
event of the DataGrid
. But this functionality is some what different in the GridView
control. It directly calls the handler of the control.
I mean to say that in the GridView
control, if you add a template column having a GridView
inside it and then if you select the Column Sorting command, it will not call any event of the master grid, but will directly call the sorting handler of the child grid. It is up to the user to take advantage of this feature.
So let me explain the code now. Here, I have a master table which is bind to the master grid using MasterDataSouce
and a child table which is bound to a GridView
inside a template column of the master grid. To bind the child grid to the ChildDataSource
, we have to use the RowDataBound
event which is called every time when a row from the database is bound to the GridView
’s row.
Here, the basic idea behind caching is that when a cell value is required, you should get it and show it. So what happens behind the screen is:
RowDataBound event of the master grid
Protected Sub grdMaster_RowDataBound(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
Handles grdMaster.RowDataBound
Dim objListItem As DataControlRowState
objListItem = e.Row.RowState
Dim intMAsterID1 As Integer
If e.Row.RowType = DataControlRowType.DataRow Then
Dim grd As GridView
If objListItem = 5 Then
grd = CType(e.Row.FindControl("grdChildGridEdit"), GridView)
MasterTableID = Convert.ToInt32(CType(e.Row.DataItem, _
DataRowView).Row.ItemArray(0).ToString())
intMAsterID1 = MasterTableID
ElseIf objListItem = DataControlRowState.Normal Or _
objListItem = DataControlRowState.Alternate Then
grd = CType(e.Row.FindControl("grdChildGridNormal"), GridView)
intMAsterID1 = Convert.ToInt32(CType(e.Row.DataItem, _
DataRowView).Row.ItemArray(0).ToString())
Dim lnkButtton As LinkButton
lnkButtton = CType(e.Row.FindControl("Edit"), LinkButton)
If lnkButtton IsNot Nothing Then
lnkButtton.CommandName = "Edit Master"
lnkButtton.CommandArgument = intMAsterID1.ToString
End If
ElseIf objListItem = DataControlRowState.Edit Then
grd = CType(e.Row.FindControl("grdChildGridEdit"), GridView)
MasterTableID = Convert.ToInt32(CType(e.Row.DataItem, _
DataRowView).Row.ItemArray(0).ToString())
intMAsterID1 = MasterTableID
End If
If grd IsNot Nothing Then
grd.DataSourceID = ""
grd.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = intMAsterID1
ChildDataSource.Select()
grd.DataBind()
End If
End If
End Sub
Here, what I am doing is when the master table's rows are bound with the GridView
's row, I find the ChildGrid
control and then bind that control with the ChildDataSource
for that MasterID
.
The above code will be used when the user hits on the Master Grid Edit button. So, in the template column, the child grid with the edit and the delete options will get visible. Now, the biggest problem with this child grid is that each and every event handler have to be written manually because the grid will lose its binding when any command gets fired. And another thing is that unlike the DataGrid
, the child grid’s handler will get called when any command of the child grid gets fired like Edit, Delete, Sorting, or Paging. In the DataGrid
, the inner control's event will be first handled by the grid's ItemCommand
event irrespective of whether that control is a DataGrid
, Button
, or ListBox
. But here it will not call the RowCommand
event of the master grid, but will directly call the RowCommand
event of the child grid. So, the event flow is like this:
- When the user presses the Edit option in the master grid, it will call the
RowCommand
event of the master grid with the command name "Edit".
- Now, it will call the
RowDataBound
of the master grid here. You will find whether the RowState
of the particular row is "Edit", and then you will find the child grid with the Edit and Delete commands in the EditTemplate
of the template column. And then you will bind the grid to ChildDataSource
.
- Now, the master grid will look like below:

- When you press the Edit option of the child grid, it will invoke the
RowCommand
of the child grid just like a DataGrid
calls the ItemCommand
of the master grid. And it will not call the RowDataBound
of the master grid so your child edit grid for that particular row will not bind to the datasource. So your grid will disappear. Now, in the RowCommand
of the child grid, you have to rebind the grid with the data source.
grdchildgrid = CType(sender, GridView)
If e.CommandArgument IsNot Nothing Then
If IsNumeric(e.CommandArgument) Then
intRowId = Convert.ToInt32(e.CommandArgument)
End If
End If
If e.CommandName.Equals("Edit") Then
grdchildgrid.DataSourceID = ""
grdchildgrid.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = MasterTableID
ChildDataSource.Select()
End If
If e.CommandName.Equals("Update") Then
UpdateChildRecord()
grdchildgrid.DataSourceID = ""
grdchildgrid.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = MasterTableID
ChildDataSource.Select()
End If
If e.CommandName.Equals("Delete") Then
DeleteChildRecord()
grdchildgrid.DataSourceID = ""
grdchildgrid.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = MasterTableID
ChildDataSource.Select()
End If
If e.CommandName.Equals("Cancel") Then
grdchildgrid.DataSourceID = ""
grdchildgrid.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = MasterTableID
ChildDataSource.Select()
End If
If e.CommandName.Equals("Page") Then
grdchildgrid.EditIndex = -1
grdchildgrid.DataSourceID = ""
grdchildgrid.DataSource = ChildDataSource
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = MasterTableID
ChildDataSource.Select()
End If
If e.CommandName.Equals("Sort") Then
grdchildgrid.EditIndex = -1
Dim dt As DataView
grdchildgrid.DataSourceID = ""
ChildDataSource.SelectParameters(_
"MasterTableID").DefaultValue = MasterTableID
dt = CType(ChildDataSource.Select(), DataView)
If ViewState.Item("SortDirection") IsNot Nothing Then
If CType(ViewState.Item("SortDirection"), _
SortDirection) = SortDirection.Ascending Then
dt.Sort = e.CommandArgument & " ASC"
ViewState.Item("SortDirection") = _
SortDirection.Descending
Else
dt.Sort = e.CommandArgument & " DESC"
ViewState.Item("SortDirection") = _
SortDirection.Ascending
End If
End If
grdchildgrid.DataSource = dt
grdchildgrid.DataBind()
End If
Here, you will find that you have to handle every command manually, for the child grid, because you are continuously changing the binding of the child grid. And another thing I have found is that if you do not write the handlers for the Edit, Delete, Update, Sort, and Page commands, it will give an error because when you press the Edit command of the child grid, it will search for the RowEditing
handler of the child grid even if you are doing all the activity in the RowCommand
event.
The grid will look like this:

- Here, one thing that is important is that in the
RowCommand
event of the child grid, you will get the old values in the grid, from the viewstate of the grid. But the child grid will not be bound to any data source if you don't bind it to in the RowCommand
event.
- When you press
UpdateCommand
, it will call the RowCommand
with the CommandArgument
as "Update". And after that, it will call the RowUpdating
event of the child grid. But there will be no values in either e.NewValues
or e.OldValues
. So you will have to do the update in the RowCommand
event.
Points of interest
ASP.NET 2.0 is a very good framework to work with. It is a much enhanced version and is very much handy to work with.
History
I will release a few more interesting articles on ASP.NET 2.0. If any body has any problems using DataGrid
control, please let me know and I will try to work on it.