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

Gridview Inside a GridView in ASP.NET 2.0

, 30 May 2006
Rate this:
Please Sign up or sign in to vote.
An article on how to use a GridView control in ASP.NET 2.0, having multiple controls in templates inside it.

Master and Chid GridView In Normal Mode

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:

  1. 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".
  2. 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.
  3. Now, the master grid will look like below:

Master GridView in Edit Mode.

  1. 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:

Master and Child GridView in Edit Mode.

  1. 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.
  2. 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.

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

Share

About the Author

Nikhil Contractor
Software Developer (Senior) Self Employed
India India
I am working as Software Profession in Sungard Offshore Services.Basically i have stared with Java,Java servlet and oracle then shifted to .Net.Since 3.5 years i am working in .Net.I am very much impressed with my one Project leader Mr.Deep Ambarkar.I have learnt so much things form him and i am very much thankful to him.

Comments and Discussions

 
Generalhi master Pinmembermohammed mana21-Apr-09 14:01 
GeneralRe: hi master PinmemberNikhil Contractor27-Apr-09 20:59 

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
Web02 | 2.8.141223.1 | Last Updated 30 May 2006
Article Copyright 2006 by Nikhil Contractor
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid