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.
- First off, create a standard .aspx web forms page and drag a Gridview and a SqlDataSource (my example will use the AdventureWorks Sample DB).
- Configure the SqlDataSource to connect to the Production.Products table. The code should look like:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
SelectCommand="SELECT * FROM Production.Product">
</asp:SqlDataSource>
-
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:
<asp:GridView ID="GridView1" runat="server"
DataSourceID="SqlDataSource1"
AllowPaging="True"
AllowSorting="True" AutoGenerateColumns="False">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />
<asp:BoundField DataField="Color" HeaderText="Color" SortExpression="Color" />
<asp:BoundField DataField="ListPrice" DataFormatString="{0:c}" HeaderText="List Price"
HtmlEncode="False" SortExpression="ListPrice" />
<asp:TemplateField HeaderText="Product List Price History" InsertVisible="False" SortExpression="ProductID">
<ItemTemplate>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView
-
Next, drag another GridView and a SqlDataSource into the ItemTemplate section of the TemplateField in the source code editor. See below:
<asp:TemplateField HeaderText="Product List Price History" InsertVisible="False" SortExpression="ProductID">
<ItemTemplate>
<asp:GridView ID="GridView2" runat="server">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource2" runat="server"></asp:SqlDataSource>
</ItemTemplate>
</asp:TemplateField>
-
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:
<ItemTemplate>
<asp:GridView ID="GridView2" runat="server"
AutoGenerateColumns="False"
DataKeyNames="ProductID,StartDate"
DataSourceID="SqlDataSource2">
<Columns>
<asp:BoundField DataField="ListPrice"
DataFormatString="{0:c}"
HeaderText="List Price"
HtmlEncode="False" SortExpression="ListPrice" />
<asp:BoundField DataField="ModifiedDate"
DataFormatString="{0:d}"
HeaderText="Modified Date"
HtmlEncode="False" SortExpression="ModifiedDate" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
SelectCommand="SELECT * FROM Production.ProductListPriceHistory">
</asp:SqlDataSource>
</ItemTemplate>
- 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:
<asp:SqlDataSource ID="SqlDataSource2" runat="server"
ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
SelectCommand='<%# Eval("ProductID", "SELECT * FROM Production.ProductListPriceHistory WHERE ProductID = {0} ")%>' >
</asp:SqlDataSource>
Notice that we have to use single quotes to delimit the SelectCommand property so that the Eval engine can then use double quotes. - 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:

» Nested Gridviews in ASP.NET 2.0
(1)
(0)
Diet (10)
Fambly (40)
Geek Stuff (59)
Music (15)
Net Junk (84)
News (111)
thank you!!! this is great!…and, very well written and ez to follow! thanks.