Nested Gridviews in ASP.NET 2.0

The other day at work I figured out a clever way to nest Gridview controls without doing any work with Datasets in the code-behind, which is the the only other method I've ever found. Since I haven't seen any instances of my method on the 'net, I thought I'd write up a quick blog entry so other folks could benefit. If you are using standard paging, the most data source connections you will have will be eleven; hardly cause for worrying about server utilization.


  1. First off, create a standard .aspx web forms page and drag a Gridview and a SqlDataSource (my example will use the AdventureWorks Sample DB).
  2. Configure the SqlDataSource to connect to the Production.Products table. The code should look like:

    <style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>SqlDataSourcestyle='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:red'>ID="SqlDataSource1"
    runat="server"

    ConnectionStringstyle='color:blue'>="<%style='font-size:10.0pt;font-family:"Courier New";background:white'>$
    ConnectionStrings:AdventureWorksConnectionString %>style='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>"

    SelectCommandstyle='color:blue'>="SELECT * FROM Production.Product">

    </aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>SqlDataSourcestyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>


  3. Next, configure the GridView to use the SqlDataSource and add a few basic columns, including ProductID as the last column as a TemplateField. This is where we will embed the nested GridView, so make sure you use the ItemTemplate and delete the EditItemTemplate. Here is my example:

    <style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>GridViewstyle='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:red'>ID="GridView1"
    runat="server"

    DataSourceIDstyle='color:blue'>="SqlDataSource1"

    AllowPagingstyle='color:blue'>="True"

    AllowSortingstyle='color:blue'>="True" AutoGenerateColumnsstyle='color:blue'>="False">

    <style='color:maroon'>Columns>

    <style='color:maroon'>asp:style='color:maroon'>BoundField DataFieldstyle='color:blue'>="Name" HeaderTextstyle='color:blue'>="Name" SortExpressionstyle='color:blue'>="Name" />

    <style='color:maroon'>asp:style='color:maroon'>BoundField DataFieldstyle='color:blue'>="ProductNumber" HeaderTextstyle='color:blue'>="Product Number" SortExpressionstyle='color:blue'>="ProductNumber" />

    <style='color:maroon'>asp:style='color:maroon'>BoundField DataFieldstyle='color:blue'>="Color" HeaderTextstyle='color:blue'>="Color" SortExpressionstyle='color:blue'>="Color" />

    <style='color:maroon'>asp:style='color:maroon'>BoundField DataFieldstyle='color:blue'>="ListPrice" DataFormatStringstyle='color:blue'>="{0:c}" HeaderTextstyle='color:blue'>="List Price"

    HtmlEncode="False" style='color:red'>SortExpression="ListPrice"
    />

    <style='color:maroon'>asp:style='color:maroon'>TemplateField HeaderTextstyle='color:blue'>="Product List Price History" style='color:red'>InsertVisible="False"
    SortExpression="ProductID">

    <ItemTemplatestyle='color:blue'>>

    </ItemTemplatestyle='color:blue'>>

    </style='color:maroon'>asp:style='color:maroon'>TemplateField>

    </style='color:maroon'>Columns>

    </aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>GridView



  4. Next, drag another GridView and a SqlDataSource into the ItemTemplate section of the TemplateField in the source code editor. See below:

    <style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>TemplateFieldstyle='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:red'>HeaderText="Product List
    Price History"
    InsertVisiblestyle='color:blue'>="False" SortExpressionstyle='color:blue'>="ProductID">

    style='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'><style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>ItemTemplatestyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>

    <asp:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>GridViewstyle='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:red'>ID="GridView2"
    runat="server">

    style='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:blue'></aspstyle='color:blue'>:GridViewstyle='color:blue'>>

    style='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:blue'><aspstyle='color:blue'>:SqlDataSource style='color:red'>ID="SqlDataSource2"
    runat="server"></style='color:maroon'>asp:style='color:maroon'>SqlDataSource>

    style='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'></style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>ItemTemplatestyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>

    </aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>TemplateFieldstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>


  5. Now switch to Design view and click Edit Templates on the SmartButton for GridView1. Now point the SqlDataSource at the ProductListPriceHistory table and then bind GridView2 to SqlDataSource2. In source view, the ItemTemplate section should now look like this:

    <style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>ItemTemplatestyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>

    <style='color:maroon'>asp:style='color:maroon'>GridView IDstyle='color:blue'>="GridView2" runatstyle='color:blue'>="server"

    AutoGenerateColumnsstyle='color:blue'>="False"

    DataKeyNamesstyle='color:blue'>="ProductID,StartDate"

    DataSourceIDstyle='color:blue'>="SqlDataSource2">

    <style='color:maroon'>Columns>

    <asp:style='color:maroon'>BoundField DataFieldstyle='color:blue'>="ListPrice"

    style='color:red'>DataFormatString="{0:c}"

    style='color:red'>HeaderText="List
    Price"

    style='color:red'>HtmlEncode="False"
    SortExpression="ListPrice"
    />

    <asp:style='color:maroon'>BoundField DataFieldstyle='color:blue'>="ModifiedDate"

    style='color:red'>DataFormatString="{0:d}"

    style='color:red'>HeaderText="Modified
    Date"

    style='color:red'>HtmlEncode="False"
    SortExpression="ModifiedDate"
    />

    </style='color:maroon'>Columns>

    </style='color:maroon'>asp:style='color:maroon'>GridView>

    <style='color:maroon'>asp:style='color:maroon'>SqlDataSource IDstyle='color:blue'>="SqlDataSource2" runatstyle='color:blue'>="server"

    ConnectionStringstyle='color:blue'>="<%style='font-size:10.0pt;font-family:"Courier New";background:white'>$
    ConnectionStrings:AdventureWorksConnectionString %>style='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>"style='font-size:10.0pt;font-family:"Courier New";background:white'>

    SelectCommandstyle='color:blue'>="SELECT * FROM
    Production.ProductListPriceHistory">

    </style='color:maroon'>asp:style='color:maroon'>SqlDataSource>

    </ItemTemplatestyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>


  6. Now comes the sneaky part. Were are going to use the String.Format functionality of the Eval one-way databinding syntax to dynamically change the SelectCommand for SqlDataSource2 for each parent row in GridView1. Here's what it looks like:

    <style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>SqlDataSourcestyle='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:red'>ID="SqlDataSource2"
    runat="server"

    ConnectionStringstyle='color:blue'>="<%style='font-size:10.0pt;font-family:"Courier New";background:white'>$
    ConnectionStrings:AdventureWorksConnectionString %>style='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>"style='font-size:10.0pt;font-family:"Courier New";background:white'>

    SelectCommandstyle='color:blue'>='<%# Eval("ProductID",
    "SELECT * FROM Production.ProductListPriceHistory WHERE ProductID = {0} ")
    style='font-size:10.0pt;font-family:"Courier New";background:yellow'>%>style='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>'style='font-size:10.0pt;font-family:"Courier New";background:white'> style='color:blue'>>

    </aspstyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>:style='font-size:10.0pt;font-family:"Courier New";color:maroon;background:white'>SqlDataSourcestyle='font-size:10.0pt;font-family:"Courier New";color:blue;background:white'>>




    Notice that we have to use single quotes to delimit the SelectCommand property so that the Eval engine can then use double quotes.

  7. If so set up everything right (and I copied it into this listing right) you should see output like this on Page 31 of the GridView1 control:

    NestedGridview1.png