GridView Inside GridView in VB.NET

Introduction

This article is very useful to all the users who are working with ASP.Net 2.0 GridView control. Here I am explaining how to work with GridView control in ASP.Net 2.0 which is very easier then DataGrid Control in ASP.Net 1.1. I will also explain what are the differences in GridView and Datagrid Control in ASP.Net 1.1. I want to explain how to work with template column having datagrid inside.

Background

The basic idea behind this article is to workout with ASP.Net 2.0's GridView Control than the DataGrid Control in ASP.Net 1.1. As I had worked with DataGrid Control so I knew how difficult to work with it in same project. I had done almost same project in ASP.Net 1.1 also. But to work with ASP.Net 2.0 GridView control is too good, easy and very user friendly. Though I had faced lot of difficulties in this but still I can say it is far better then ASP.Net 1.1's grid control for some functionality. GridView control gives you Edit, Update, Delete, Sorting, Selection and Paging facility built in.

Using the code

Here in this project, I have used ObjectDataSource control for binding the GridView to the data. This is one of the best features available in VS.Net 2005. It is very easy to work with it.

The main difference between DataGrid and GridView control is that the first one has central event handling which means any event raised by control inside the DataGrid's template column will be handled by ItemCommand event of datagrid. But this functionality is some what different in GridView Control. It directly calls the handler of the control.

I mean to say that in GridView Control if you have added one template column having GridView inside it and now if you select "Column Sorting" command then it will not call any event of Master grid. It 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 one MasterTable which is bind to the Master Grid using MasterDataSouce and one ChildTable which is bind to Gridview inside template column of Mastergird. To bind the Child Grid to ChildDataSource we have to use RowDataBound event which is called every time when each row from database is bind to the Grid View's row.

Here, basic idea behind caching is that when cell value is required you should get it and show it. So what happen behind the screen is:

RowDataBound event of Mastergrid

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 master table's each row bind with the GridView's row I am finding the ChildGrid Control then binding that control with ChildDataSource for that MasterID.

Above code will be used when user hits on Master Grid Edit button. So In the Template Column child grid with edit and delete option will get visible. Now, the biggest problem with this child grid is that each and every event you to write manually because grid will lost it's binding when any command is get fired. And another thing is that unlike ASP.Net1.1's datagrid child grid's handler will get called when any command of childgird get fired like Edit, Delete, Sorting, Paging. In ASP.Net1.1 Data grid's Inner control's event will be first handled by Grid's Item Command event irrespective of whether that control is DataGrid, Button, List Box etc. But here it will not call the RowCommand event of Master Grid it will directly call RowCommand event of ChildGrid. So event flow is like this

1. When User Press Edit Command is Master Grid it will call RowCommand Event of MasterGrid with Command Name as "Edit".

2. Now it will call RowDataBound of Mastergrid here you will find the whether the RowState of particular Row is edit then you will find ChildGrid with Edit and Delete Command in the EditTempalate of Template Column. And Bind the grid to ChildDataSource.

3. Now, MasterGrid will look like below:

gridview-in-vb.net.gif

4. When you press EditCommand of ChildGrid it will RowCommand of ChildGrid unlike ASP.Net1.1 's Datagrid call the ItemCommand of Mastergrid. And it will not call the RowDataBound of MasterGrid so your child edit grid for that particular row will not bind to datasource. So your grid will get disappear. Now, here you in RowCommand of child grid you have to rebind the grid with the datasource.

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 binding of child grid. And one thing I have found that if you did not write handler of edit, delete, update, sort, page command it will give error because when you press Edit Command of Child Grid it will find for the RowEditing Handler of child grid even if you are doing your all the activity in RowCommand event.

5. Here one thing is important is that in RowCommand event of Child Grid you will get the old values in the grid means viewstate of the grid. But the childgrid will not be bind to any data source if you don't bind it to in RowCommand event.

6. When you press UpdateCommand it will call RowCommand with CommandArgument as "Update". And after it will call the RowUpdating event of the ChildGrid. But there no values will be there in either e.NewValues or e.OldValues.

Points of Interest

ASP.NET 2.0 is very good to work with. It is so much enhanced version and very much handy to work.

MSDN LINK

History

This is first version of GridControl. I will release few more interesting articles on ASP.Net 2.0. If any body has any typical problem in Datagrid I will try to work out on that.


Similar Articles