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

Editable Nested DataGrid

, 11 Mar 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
How to Create a Nested DataGrid in ASP.NET Using C#
Screenshot - EditNestedGridView.JPG


This article explains how to make an ASP.NET Editable Nested GridView. Here I am going to explain how to provide all the features of Edit/Add/Delete/Update/Page/Sort of a GridView, and not only one GridView, but I am going to explain how to extend these features to even nested grids (GridView inside GridView). I have provided the fully functional source code, which is self-explanatory.


My previous article explains about the features of Nested Editable DataGrid. This article provides all those features in GridView (Visual Studio 2005, .NET 2.0). With the combination of GridView and DataSource controls, it's very easy to create an Editable GridView.

Using the Code

This is a web application with a virtual directory named EditNestedGridView. You may create the same virtual directory to run this application with Visual Studio .NET 2005 or create any other virtual directory and map the path to this directory to access it from the browser. As I have used Access 2003 as my database, you need to have Microsoft Access installed on your machine. I have used NorthWind database with some modifications. I have included this also in the code bundle under the App_Data folder. I have used C# for codebehind files. In Visual Studio 2005, File --> Open --> Web Site and navigate to the folder EditNestedGridView.

Step-by-Step Procedure

The code attached is self-explanatory, but will try to explain as much as possible.

1. Since here I am going to use the DataSource control, let's first create a Access DataSource control as mentioned below.

<asp:AccessDataSource ID="AccessDataSource1" runat="server" 
    SelectCommand="SELECT [Customers].[CustomerID], 
    [Customers].[ContactTitle],[Customers].[Address] FROM [Customers] 
    ORDER BY [Customers].[CustomerID]"></asp:AccessDataSource>

The main advantage of the DataSource control is that it simplifies the amount of custom code that needs to be written to retrieve and bind data, and even to sort, page through or edit data.

2. Now let's create a simple GridView control and attach the previously created DataSource control as below.

<asp:GridView ID="GridView1" AllowPaging="True" BackColor="#f1f1f1" 
            AutoGenerateColumns=false DataSourceID="AccessDataSource1" 
            style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 32px" 
            ShowFooter=true Font-Size=Small
            Font-Names="Verdana" runat="server" GridLines=None BorderStyle=Outset>

GridView is very similar to DataGrid and it has all those column features of DataGrid like TemplateColumn, BoundColumn to populate data as columns. EditItemTemplate and FooterTemplate can be used for editing and adding purpose. Following code shows the columns of parent Grid.

<asp:TemplateField HeaderText="Customer ID" SortExpression="CustomerID">
        <asp:Label ID="lblCustomerID" Text='<%# Eval("CustomerID") %>' 
        <asp:Label ID="lblCustomerID" Text='<%# Eval("CustomerID") %>' 
        <asp:TextBox ID="txtCustomerID" Text='' runat="server"></asp:TextBox>
<asp:TemplateField HeaderText="Company Name" SortExpression="CompanyName">
    <ItemTemplate><%# Eval("CompanyName") %></ItemTemplate>
        <asp:TextBox ID="txtCompanyName" Text='<%# Eval("CompanyName") %>' 
        <asp:TextBox ID="txtCompanyName" Text='' runat="server"></asp:TextBox>

<asp:CommandField HeaderText="Edit" ShowEditButton="True" />
<asp:TemplateField HeaderText="Delete">
        <asp:LinkButton ID="linkDeleteCust" CommandName="Delete" 
        <asp:LinkButton ID="linkAddCust" CommandName="AddCustomer" 

Now that we have all the columns in place, we need the event handlers to take care of Add/Edit/Delete actions. Handling these events is very straightforward compared to DataGrid. The DataSource control takes care of the Paging and Sorting actions. Here is the final parent GridView control with all these events.

<asp:GridView ID="GridView1" AllowPaging="True" BackColor="#f1f1f1" 
            AutoGenerateColumns=false DataSourceID="AccessDataSource1" 
            style="Z-INDEX: 101; LEFT: 8px; POSITION: absolute; TOP: 32px" 
            ShowFooter=true Font-Size=Small
            Font-Names="Verdana" runat="server" GridLines=None 
            OnRowCommand = "GridView1_RowCommand" 
            OnRowUpdating = "GridView1_RowUpdating" BorderStyle=Outset
            OnRowDeleting = "GridView1_RowDeleting" 
            OnRowDeleted = "GridView1_RowDeleted"
            OnRowUpdated = "GridView1_RowUpdated" AllowSorting=true>

With all the above options, GridView looks like below.

Screenshot - EditNestedGridView1.jpg

3. Until now, we have created parent a GridView. Now we are going to extend these features in a child GridView as well.

Before adding another GridView, we must understand how GridView emits its content as HTML tags. For an Internet Explorer browser, GridView is like a regular Table with TR and TD tags. So, if we can manipulate the parent GridView to forcibly close a row and emit Child GridView as another ROW, we are done with it.

What is displayed is some HTML table cell and row tags that effectively intercept the current output that will be generated by the GridView with our own special implementation. Namely, we are telling the table (when it's drawn) to close the current cell, the current row and now add a new row with one blank column (for spacing) and another column (spanning all columns) that we'll use to display a second GridView. Here is the piece of code which explains this:

        <td colspan="100%">
        <div id="div<%# Eval("CustomerID") %>" 
            style="display:none;position:relative;left:15px;OVERFLOW: auto;WIDTH:97%" >

Here I have created a division id="div Eval("CustomerID") with an ID of Customer (parent row) which holds Child GridView so that we can dynamically hide and expand it by using DIV ID. Also, we need a column in the main GridView which holds the image to expand and collapse the child GridView as below.

        <a href="javascript:expandcollapse('div<%# Eval("CustomerID") %>', 'one');">

Here the JavaScript function expandcollapse will take care of expand and collapse action.

4. In order to bind the Child GridView, we can't use static DataSource control as we have used for parent GridView. We will have to dynamically prepare the query based on the Customer ID of the corresponding parent row and that we can do it in RowDataBound event of the parent Grid as below.

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        GridViewRow row = e.Row;
        string strSort = string.Empty;

        // Make sure we aren't in header/footer rows
        if (row.DataItem == null)

        //Find Child GridView control
        GridView gv = new GridView();
        gv = (GridView)row.FindControl("GridView2");

        //Prepare the query for Child GridView by passing 
        //the Customer ID of the parent row
        gv.DataSource = 

Here the ChildDataSource function forms the query using the passed Customer ID and returns AccessDataSource.

5. Now we have data in Child Grid as well with dynamic expand and collapse. Let's add effects one by one as we did for parent grid. However, before going further, there is a little tricky part involved. In the case of the parent grid, there is only a unique ID (GridView1) and in the case of the child there will be several unique IDs that get generated at run time. If we can identify the one which we need, that will solve this problem.

Paging and Sorting were taken care of by DataSource control in the case of the parent grid. For the child grid, we have to take care of it manually using the corresponding events PageIndexChanging and Sorting. A sample code of paging event looks like below.

protected void GridView2_PageIndexChanging(object sender, GridViewPageEventArgs e)
        GridView gvTemp = (GridView)sender;
        gvUniqueID = gvTemp.UniqueID;
        gvNewPageIndex = e.NewPageIndex;

Here we have identified the run time Unique ID of the child grid which needs paging along with the new page number. We are going to use these variable values in the RowDataBound event of the parent grid as below.

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
        //Find Child GridView control
        GridView gv = new GridView();
        gv = (GridView)row.FindControl("GridView2");
        //Check if any additional conditions (Paging, Sorting, Editing, etc) 
        //to be applied on child GridView
        if (gv.UniqueID == gvUniqueID)
            gv.PageIndex = gvNewPageIndex;
            gv.EditIndex = gvEditIndex;
            //Check if Sorting used
            if (gvSortExpr != string.Empty)
                strSort = " ORDER BY " + string.Format("{0} {1}", gvSortExpr, gvSortDir);
            //Expand the Child grid
            ClientScript.RegisterStartupScript(GetType(), "Expand", 
                "<script language="javascript"></script>");

The remaining actions (Sorting/Edit/Update/Delete) can also be handled similarly to paging. Refer to the source code attached above.


GridView has more features compared to DataGrid, which will make it easier to code and also we can include HTML tags in between for more flexibility.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Veera V Satya N Kanithi
United States United States
No Biography provided

Comments and Discussions

QuestionInsert a Child row to Parent gridrow where there is no childrow currently existing Pinmembersreegouri26-Mar-15 12:09 
GeneralHow flip sql statements? Pinmembermeryem1118-Jan-13 2:20 
QuestionA Compound Sample Pinmemberstsalt4-Nov-12 21:30 
QuestionRegarding nested grid Pingroupradhika 56-Feb-12 22:51 
QuestionPlus Image disappears after clicking it! Pinmembersu_ma201028-Sep-11 19:55 
QuestionAll children are expanded PinmemberAndiH202-Aug-11 13:12 
GeneralMy vote of 5 PinmemberDilip Baboo15-Jul-11 10:08 
GeneralRe: My vote of 5 Pinmembersu_ma201029-Sep-11 18:49 
Generalpls help me Pinmembervenkatvenkat12314-Apr-11 22:59 
GeneralProblem in deep levels of nested grid..please help Pinmembervinod chattergee16-Jun-10 19:08 
GeneralNested GridView With Checkbox Pinmembercbmsuresh24-Dec-09 0:11 
QuestionGrid PinmemberMrLoor24-Nov-09 3:54 
GeneralNeed help for retrieving nodes from XML Menu Files stored onto the Sql server Pinmemberbrightsy_mary15-Sep-09 4:27 
QuestionWhat changes we have to do for using sqlDataSource instead for accessDataSource Pinmembertaps673120-May-09 0:40 
AnswerRe: What changes we have to do for using sqlDataSource instead for accessDataSource Pinmembercrowt48-Jul-09 5:45 
GeneralHi i have some problem Pinmembersantosh d4-May-09 19:48 
GeneralAccessing Parent row from Child PinmemberMuniappan26-Jan-09 10:53 
GeneralRe: Accessing Parent row from Child PinmemberMuniappan26-Jan-09 12:51 
GeneralVisual Studio 2008 PinmemberMadMaxx8-Jan-09 9:43 
QuestionHELP =&gt; Order from 1st page selected when editing orders for customers with multiple orderpages PinmemberDivolt14-Nov-08 18:06 
GeneralNested GridView and FormView PinmemberAggiefan9418-Sep-08 10:14 
GeneralHelp with Nested Grid..!! Pinmemberqtrmile6916-Jul-08 7:27 
Generalcheckbox in nested datagridview Pinmembertarang26-Jun-08 21:38 
Generalthis project in dotnet2003, framework 1.1, or something like this Pinmemberrostamimehdi4-Apr-08 6:08 
I need to know, to do something like this in framework 1.1, do you have something special??
GeneralRe: this project in dotnet2003, framework 1.1, or something like this PinmemberSatya Kanithi16-Jun-08 14:49 
GeneralReally Nice But i could not implement in Pinmembershenmoorthy17-Feb-08 23:51 
GeneralRe: Really Nice But i could not implement in Pinmemberwolf_tiger23-Mar-08 11:05 
GeneralRe: Really Nice But i could not implement in Pinmemberkarlawain3-Nov-08 15:29 
QuestionEmpty Data Pinmemberedypangaribuan8-Feb-08 10:57 
AnswerRe: Empty Data Pinmemberdave.dolan16-Jun-08 10:22 
GeneralRe: Empty Data PinmemberSatya Kanithi16-Jun-08 14:46 
QuestionRe: Editable Nested Gridview Pinmemberbamagrad24-Jan-08 6:46 
GeneralC# code PinmemberHariSir30-Nov-07 5:41 
Generalnice article Pinmemberrdvsharma20-Nov-07 23:15 
GeneralPlaceHolder Tag Error PinmemberKim Chen15-Oct-07 12:21 
GeneralPlaceHoder Tag Error PinmemberKim Chen15-Oct-07 11:52 
GeneralReexpand parent after saved child Pinmembermullemeck15-Oct-07 5:18 
GeneralRe: Reexpand parent after saved child Pinmembermullemeck15-Oct-07 5:47 
GeneralC# code, please 23:15 
GeneralSorting Problem in Nested Datagrid PinmemberRupali Rane22-Aug-07 1:07 
GeneralChild Datagrid Sorting Error PinmemberRupali Rane22-Aug-07 1:05 
GeneralProblem Regarding Nested Datagrid PinmemberRupali Rane22-Aug-07 1:02 
GeneralGot an error PinmemberNagendra Kumar20-Aug-07 22:31 
AnswerRe: Got an error PinmemberSatya Kanithi21-Aug-07 5:14 
GeneralSimilar Solution using GridView PinmemberSatya Kanithi19-Aug-07 16:33 
GeneralC# code PinmemberT_Kan15-Aug-07 12:45 
GeneralRe: C# code PinmemberHariSir30-Nov-07 10:47 
QuestionDataBinder.Eval: 'System.Data.DataRowView' does not contain a property with the name OrderId. Pinmembernaga praveen mulukutla9-Aug-07 22:14 
AnswerRe: DataBinder.Eval: 'System.Data.DataRowView' does not contain a property with the name OrderId. PinmemberSatya Kanithi13-Aug-07 8:46 
QuestionOrderId is neither a DataColumn nor a DataRelation for table ChildTable. Pinmembernaga praveen mulukutla9-Aug-07 22:11 

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.150414.1 | Last Updated 11 Mar 2007
Article Copyright 2006 by Veera V Satya N Kanithi
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid