How to fire RowCommand event of nested GridView?

In ASP.Net you can use a Repeater or GridView controls to simply display any data collection came from any data source(database,XML file,...etc). Sometimes each item of that collection has a property that is another collection and to display it you will use another Repeater or another GridView(nested Repeater or nested GridView).

To edit, delete or to execute a command on any GridView row you use OnRowCommand event to handle it, but what about the commands on the child(nested) GridView rows. In case of nested Repeater you can set the OnItemCommand event of the child Repeater. You can find many articles explain how to do that. The problem which my friend faced is handling the OnRowCommand event of nested GridView. We googled it but we didn't find a lot of article that explain how to handle it, so I write this post to help any one facing the same issue.

Assume we have a set of Inventories, each Inventory have a set of products. To display All inventories with all products of each one, we will use a GridView for inventories main properties and a nest GridView to list the products of each inventory.
class Inventory
{
    public String Name { get; set; }
    public Int32 Id { get; set; }
    public List<Product> Products { get; set; }
}
class Product
{
    public String Name { get; set; }
    public Int32 Id { get; set; }
    public Int32 Quantity { get; set; }
}
The following image shows our GridView. Note the third column lists the products of an inventory, the forth column in the products grid is button to delete the corresponding product. This is the command that we want to execute.
We will bind the GridView of products inside the OnRowDataBound event of the parent GridView.
protected void inventoriesGrid_RowDataBound(Object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        GridView productsGrid = e.Row.FindControl("productsGrid") as GridView;
        productsGrid.DataSource = (e.Row.DataItem as Inventory).Products;
        productsGrid.DataBind();
        //productsGrid.RowCommand += new GridViewCommandEventHandler(productsGrid_RowCommand);
    }
}
In this event we do the following for each row of inventories GridView
  1. Check the RowType, it must be DataRow.
  2. Finding the child GridView by its ID property.
  3. Set the DataSource property of products GridView to the product list of current inventory.
  4. Call DataBind method of products GridView.
If you uncommented the commented line, that will wire the RowCommand event of products GridView to productsGrid_RowCommand event but when you will run your code this event will never be fired. Why???. To answer this question we have two scenarios :
  1. If you bind the parent GridView every time you load the page, so you re-fire its RowDataBound event every time and re-wire the RowCommand of child GridView again and again. That changes the view state of the child GridView and its RowCommand will not be fired( in PostBack ASP.Net read the old view state which is changed while binding the parent grid).
  2. If you bind the parent grid in first time you request the page(the current request is not a post back) so the RowDataBound will not fired while post back. You think that will solve the problem, No that will not solve it because the RowCreated event of parent GridView be fired every request even if it is postback. That means you need to re-wire the RowCommand of child GridView again.
The best place to wire the RowCommand of child GridView is to write this code inside the RowCreated event of parent GridView because this event be fired after the Page_Load and before handling post back event. This guarantee the RowCommand of child GridView is wired to the same event before handling it.

Again you need to find the child GridView by its ID property but this time inside the RowCreated event of the parent GridView.
protected void inventoriesGrid_RowCreated(Object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        productsGrid = e.Row.FindControl("productsGrid") as GridView;
        productsGrid.RowCommand += new GridViewCommandEventHandler(productsGrid_RowCommand);
    }
}
The RowCommand event of child GridView (products) its self
protected void productsGrid_RowCommand(Object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "deleteitem")
    {
        //Do whatever you want
    }
}
you can download the full source code here

Comments

  1. how to get CommandArgument for a linkbutton in the nested grid

    ReplyDelete
    Replies
    1. In the RowCommand event of nested grid you can get the CommandArgument by e.CommandArgument property but after checking on e.CommandName property of your LinkButton in the nested grid

      Delete
    2. is there any option directly using void ChildGridview_ItemCommand(object sender, GridViewCommandEventArgs e) for the child Gridview without using class Inventory and class Product in C# coding?

      Delete
    3. this event is related to GridView not related to its datasource. you can use it with any datasource like DataSet, DataTable, or any Generic collection. These classes used for demonstration purpose only.

      Delete
    4. Ok sir one more question and it is related to design part that is how to use child header color according to row color of parent Grid view ?

      Delete
    5. you do that by removing HeaderStyle node from child Grid and add this line into OnRowDataBound event of parent Grid

      productsGrid.HeaderRow.BackColor = e.Row.BackColor;

      Delete
    6. Great, thanks!

      Delete
  2. What is the code for VB.net?

    ReplyDelete
    Replies
    1. sorry I am so busy these days to create full example in VB.net but you can use the following links to convert C# code in .cs files to VB.net
      http://www.developerfusion.com/tools/convert/csharp-to-vb/
      http://converter.telerik.com/

      Delete
  3. Nested Gridview RowCommand event cause Parent GridView RowCommand fire

    http://stackoverflow.com/questions/30284080/nested-gridview-rowcommand-event-cause-parent-gridview-rowcommand-fire

    ReplyDelete
    Replies
    1. In my case I attach RowCommand event in runtime not in GridView definition as mentioned in stackoverflow question.

      You can download my sample and check it. frankly I have uploaded it from long long time ago and not sure if it has the same issue or not.

      Delete
  4. How to get cell values from child grid?

    ReplyDelete

Post a Comment

Popular posts from this blog

Android : How to change progress bar color at runtime programmatically?

ASP.Net MVC : Conditional Validation using ValidationAttribute