ASP.NET Nested Grid View – Expandable and Collapsible row

Introduction

ASP.NET Grid View data binding is really easy. But if you have a situation where you need to display details data once user click a row in the data grid then you need nested grid. You can accomplished this task in several ways. This article will demonstrate you the easiest one of them.

Screenshot

ASP.NET Nested Grid View

In the article I have created Customer repository but in the real time scenario there should be service layer. For simplicity I skipped the service layer.
Customer Repository

public class CustomerRepository
{
    public List<Customer> GetCustomers(int pageId = 1, int  pageSize = 10)
    {
        var db = new NWEntities();
        var customers = db.Customers
                          .OrderBy(x => x.CustomerID)
                          .Skip((pageId - 1) * pageSize)
                          .Take(pageSize)
                          .ToList();
        return customers;
    }
    public List<Order> GetCustomerOrders(string customerId)
    {
        var db = new NWEntities();
        var orders = db.Orders
                       .Where(x => x.CustomerID == customerId)
                       .ToList();
        return orders;
    }
}

ASP.NET Grid View design

<asp:GridView ID="gvCustomers" runat="server"
    DataKeyNames="CustomerID"
    Width="100%"
    GridLines="None"
    AutoGenerateColumns="false"
    OnRowDataBound="gvCustomers_RowDataBound"
    >
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <button class="btn btn-default glyphicon glyphicon-plus" onclick="return ToggleGridPanel(this, 'tr<%# Eval("CustomerID") %>')" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CustomerID" HeaderText="ID" />
        <asp:BoundField DataField="ContactName" HeaderText="Customer" />
        <asp:BoundField DataField="Address" HeaderText="Address" />
        <asp:BoundField DataField="City" HeaderText="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" />
        <asp:TemplateField HeaderText="Phone">
            <ItemTemplate>
                <%# Eval("Phone") %>
                <%# MyNewRow(Eval("CustomerID")) %>  
                    <asp:GridView ID="gvOrders" runat="server"
                        Width="100%"
                        GridLines="None"
                        AutoGenerateColumns="false"
                        DataKeyNames="CustomerID"
                        >
                        <Columns>
                            <asp:BoundField DataField="OrderID" HeaderText="Order ID" />
                            <asp:BoundField DataField="OrderDate" HeaderText="Order Date" 
                                DataFormatString="{0:MM-dd-yy}" />
                            <asp:BoundField DataField="ShippedDate" HeaderText="Shipped On" 
                                DataFormatString="{0:MM-dd-yy}" />
                            <asp:BoundField DataField="ShipName" HeaderText="Ship To Name" />
                            <asp:BoundField DataField="ShipCity" HeaderText="City" />
                        </Columns>
                    </asp:GridView>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

CSS

<style type="text/css">
    .collapsed-row {
        display:none;
        padding:0px;
        margin:0px;
    }
</style>

Java Script

<script type="text/javascript">
    function ToggleGridPanel(btn, row) {
        var current = $('#' + row).css('display');
        if (current == 'none') {
            $('#' + row).show();
            $(btn).removeClass('glyphicon-plus')
            $(btn).addClass('glyphicon-minus')
        } else {
            $('#' + row).hide();
            $(btn).removeClass('glyphicon-minus')
            $(btn).addClass('glyphicon-plus')
        }
        return false;
    }
</script>

Code behind

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
        BindGrid();
}
private void BindGrid()
{
    var customerRepository = new CustomerRepository();
    var customers = customerRepository.GetCustomers(1 , 10);
    gvCustomers.DataSource = customers;
    gvCustomers.DataBind();
}
public string MyNewRow(object customerId)
{
    return String.Format(@"</td></tr><tr id ='tr{0}' class='collapsed-row'>
        <td></td><td colspan='100' style='padding:0px; margin:0px;'>", customerId);
}

protected void gvCustomers_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        string customerId = gvCustomers.DataKeys[e.Row.RowIndex].Value.ToString();
        var gvOrders = (GridView)e.Row.FindControl("gvOrders");

        var repository = new CustomerRepository();
        var orders = repository.GetCustomerOrders(customerId);
        gvOrders.DataSource = orders;
        gvOrders.DataBind();

    }
}

Youtube video tutorial

https://www.youtube.com/watch?v=FM3iylISusw

Last Word

Today you have leaned how to create nested grid view. I hope this article helped you. You can share this article for others like us.

Comments

Email
Print