Implementing Master-Detail views with nested GridView controls

I want to illustrate how to implement nested GridViews. I will use the Authors table of Pubs database. If you recall, Pubs database is part of Microsoft SQL Server samples. We have a parent grid and a child grid. The parent grid, AuthorGrid displays last name of authors. The child grid, DetailGrid, displays more details for the selected author.

<asp:GridView ID="AuthorGrid" runat="server" DataSourceID="AuthorSql" 
                AutoGenerateColumns="false" DataKeyNames="au_lname"
                 OnSelectedIndexChanged="AuthorGrid_SelectedIndexChanged">
    <Columns>
        <asp:BoundField HeaderText="Author" DataField="au_lname" />
        <asp:TemplateField>
            <ItemTemplate>
                <asp:GridView ID="DetailGrid" runat="server" 
                OnRowCommand="DetailGrid_OK" 
                AutoGenerateColumns="false">
                    <Columns>
                        <asp:BoundField HeaderText="First name" DataField="au_fname" />
                        <asp:ButtonField CommandName="OK" Text="OK" />
                    </Columns>
                </asp:GridView>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:CommandField ShowSelectButton="true" SelectText="Show" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="AuthorSql" runat="server"
                    ConnectionString = "<%$ ConnectionStrings:Pubs %>"
                   SelectCommand="SELECT au_lname FROM Authors"
></asp:SqlDataSource>
<asp:SqlDataSource ID="DetailSql" runat="server" DataSourceMode="DataSet"
                    ConnectionString = "<%$ ConnectionStrings:Pubs %>"
                   SelectCommand="SELECT au_fname FROM Authors
                         WHERE au_lname=@lname"
>
    <SelectParameters>
        <asp:Parameter Type="String" Name="lname" />
    </SelectParameters>
</asp:SqlDataSource>

AuthorGrid is bound to a data source. The SqlDataSource, AuthorSql, has tabular data with list of author names. The child grid, DetailGrid is not bound. DetailGrid binds to a data source when we select an author in the parent grid. The OnSelectedIndexChanged event handler of the parent grid is shown below.

protected void AuthorGrid_SelectedIndexChanged(object sender, EventArgs e)
{
    string lname = (string)AuthorGrid.SelectedValue;
    DetailSql.SelectParameters["lname"].DefaultValue = lname;
    DataSourceSelectArguments dssa = new DataSourceSelectArguments();
    DataView ds = (DataView)DetailSql.Select(dssa);
    GridView DetailGrid = (GridView)AuthorGrid.SelectedRow
				.FindControl("DetailGrid");
    DetailGrid.DataSource = ds;
    DetailGrid.DataBind();
}

We retrieve the last name from the parent grid selection. Pass the last name as an argument to the data source. Retrieve the child grid from the selected row of the parent grid. Bind the child grid to the data source. That should populate the DetailGrid or child grid.

The DetailGrid has an OK button. Click the button. And the DetailGrid disappears. The code for the click event handler is shown below.

protected void DetailGrid_OK(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName == "OK")
    {
        GridView DetailGrid = (GridView)e.CommandSource;
        DetailGrid.DataBind();
    }
}

On clicking OK button, we bind the child grid to an empty data source.

In this example, we have a trivial master-detail or parent-child nested GridView. The parent grid displays last names of authors. And the child grid displays a list of first names of authors who share the same last name. Though the example is trivial, we have all the building blocks to build nested views.

Related Posts

Leave a Reply

Your email address will not be published.