This article explains how to make an ASP.NET nested GridView. There may be many ways to do this, but here is my code.
Your browser does not support iframes.
First, put gridview1 into asp design page then put another gridview2 inside previous gridview.
Here is code file
<form id="form1" runat="server"> <asp:GridView ID="GridView1" runat="server" DataKeyNames="CustomerID" AutoGenerateColumns="false" OnRowDataBound="gv_RowDataBound" Width="80%" AllowPaging="True" PageSize="20" > <HeaderStyle CssClass="dataTable" /> <RowStyle CssClass="dataTable" /> <AlternatingRowStyle CssClass="dataTableAlt" /> <Columns> <asp:TemplateField> <ItemTemplate> <a href="javascript:switchViews('div<%# Eval("CustomerID") %>', 'one');"> <img id="imgdiv<%# Eval("CustomerID") %>" alt="Click to show/hide orders" border="0" src="Images/expand_button.png" /> </a> </ItemTemplate> <AlternatingItemTemplate> <a href="javascript:switchViews('div<%# Eval("CustomerID") %>', 'alt');"> <img id="imgdiv<%# Eval("CustomerID") %>" alt="Click to show/hide orders" border="0" src="Images/expand_button.png" /> </a> </AlternatingItemTemplate> </asp:TemplateField> <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" HtmlEncode="False" /> <asp:BoundField DataField="Name" HeaderText="Name" HtmlEncode="False" /> <asp:BoundField DataField="Address" HeaderText="Address" HtmlEncode="False" /> <asp:TemplateField> <ItemTemplate> </td></tr> <tr> <td colspan="100%" > <div id="div<%# Eval("CustomerID") %>" style="display:none;position:relative;left:25px;" > <asp:GridView ID="GridView2" runat="server" Width="80%" AutoGenerateColumns="false" DataKeyNames="ItemCode" EmptyDataText="No orders for this customer." > <HeaderStyle CssClass="dataTable" /> <AlternatingRowStyle CssClass="dataTableAlt" /> <RowStyle CssClass="dataTable" /> <Columns> <asp:BoundField DataField="OrderDate" HeaderText="Order Date" HtmlEncode="False" /> <asp:BoundField DataField="ShippedDate" HeaderText="ShippedDate" HtmlEncode="False" /> <asp:BoundField DataField="ShipTO" HeaderText="Ship TO" /> </Columns> </asp:GridView> </div> </td> </tr> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </form>
In above code, To get nested gridview effect I simply injected some HTML to end the current row and create a new row. The nested GridView is then placed inside a < DIV> tag where the display of that < DIV> is controled by Javascript. Each < DIV> is assigned a unique ID that corresponds to the main GridView’s rowID and that is passed to the javascript to control the opening and closing of the nested GridView.
Second, In Codebehind file I put datasource of gridview. In order to bind the child GridView2, we can’t use the static DataSource control. We will have to dynamically prepare the query based on the customer ID of the corresponding parent row, and that we can do it in the RowDataBound event of the parent grid as below:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { SqlDataSource dbSrc= new SqlDataSource(); dbSrc.ConnectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString2"].ConnectionString; dbSrc.SelectCommand = "SELECT CustomerID, Name, Address FROM Customer"; GridView1.DataSource = dbSrc; GridView1.DataBind(); } } //The code to populate the nested GridView that is called on the main GridView's OnRowDataBound event protected void gv_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { GridView gv = (GridView)e.Row.FindControl("GridView2"); SqlDataSource dbSrc = new SqlDataSource(); dbSrc.ConnectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString2"].ConnectionString; dbSrc.SelectCommand = "SELECT OrderDate,ShippedDate, ShipTO FROM Orders where customerID='" + ((DataRowView)e.Row.DataItem)["CustomerID"].ToString() + "'"; gv.DataSource = dbSrc; gv.DataBind(); } }
Finally, put JavaScript to show/hide Child gridview ..
<script type="text/javascript"> function switchViews(obj, row) { var div = document.getElementById(obj); var img = document.getElementById('img' + obj); if (div.style.display == "none") { div.style.display = "inline"; img.src = "images/expand_button_down.png"; } else { div.style.display = "none"; img.src = "images/expand_button.png"; } } </script>
Here is css file for design purpose.
<style type="text/css"> .dataTable { text-align:left; font-size:10pt; font-family:Verdana, Sans-Serif; border:solid 1px rgb(210,210,210); color:gray; } .dataTable CAPTION { color:Black; text-align:left; font-size:12pt; font-weight:bold; padding-bottom:5px; padding-top:15px; } .dataTable TH { text-decoration:none; background-color:rgb(210,210,210); font-family:Tahoma, Sans-Serif, Arial; font-size:11pt; font-weight:normal; color:Black; border:solid 0px; padding:2px 4px 2px 2px; } .dataTable TD { padding-left:6px; border:solid 0px; min-width:100px; } .dataTable TR { border:solid 0px; } .dataTableAlt TD { font-size: 10pt; color:rgb(75,75,75); font-family:Verdana; border: solid 0px; padding:2px 0px 2px 8px; background-color:rgb(245,245,245); min-width:100px; } .dataTableRow { color:rgb(75,75,75); font-family:Verdana; padding:2px 0px 2px 8px; border:solid 0px; background-color:White; } .dataTable A:Link, .dataTable A:Visited { text-decoration:none; color:black; } .dataTable A:Hover { color:Red; text-decoration:none; } </style>
Thanks.