Monday, May 18, 2009

Nested Gridview in Asp.net 2.0

As i said in my last post that i will write about Check/ Uncheck checkboxes of Treeview on the basis of database value and i think it’s very easy so skipping that part and here i am going to write about Nested Gridview that will look like below image:
Nested Gridview
Rather than displaying Nested Gridview in the same row, we’ll display it in below row that gives user proper understanding of the data. Let’s see, How it can be done?
First of all i am using Northwind Database that comes with SQL Server and if you are not having it, you can download it.
Here’s the HTML Source Code for Parent GridView, change it according the language C# or VB and your requirement:
  1: <asp:GridView ID="gvOrders" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource1" DataKeyNames="OrderID" CellPadding="4" ForeColor="#333333">
  2:   <Columns>
  3:     <asp:TemplateField>
  4:      <ItemTemplate>
  5:        <asp:Label ID="lblSign" runat="server" />
  6:      </ItemTemplate>
  7:     </asp:TemplateField>
  8:     <asp:BoundField DataField="OrderID" HeaderText="OrderID" InsertVisible="False" ReadOnly="True" SortExpression="OrderID" />
  9:     <asp:BoundField DataField="CustomerID" HeaderText="CustomerID" SortExpression="CustomerID" />
 10:     <asp:BoundField DataField="EmployeeID" HeaderText="EmployeeID" SortExpression="EmployeeID" />
 11:     <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
 12:     <asp:BoundField DataField="Address" HeaderText="Address" SortExpression="Address" />
 13:     <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
 14:     <asp:BoundField DataField="Region" HeaderText="Region" SortExpression="Region" />
 15:     <asp:BoundField DataField="Postal" HeaderText="Postal" SortExpression="Postal" />
 16:     <asp:BoundField DataField="Country" HeaderText="Country" SortExpression="Country" />
 17:     <asp:TemplateField>
 18:      <ItemTemplate>
 19:       <tr>
 20:        <td colspan="100%">
 21:         <div id="div<%#Eval("OrderID") %>" style="display: none; position: relative;">
 22:         </div>
 23:        </td>
 24:       </tr>
 25:      </ItemTemplate>
 26:     </asp:TemplateField>
 27:   </Columns>
 28:   <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
 29:   <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
 30:   <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
 31:   <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
 32:   <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
 33:   <EditRowStyle BackColor="#999999" />
 34:   <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
 35: </asp:GridView>

In above code we’ve inserted <tr> and <td> and <div> tag that is highlighted by Yellow background colour. Gridview is rendered as HTML table and GridView rows will be rendered as <tr> and cells will be as <td> so that we are explicitly inserting those tags to show our child Gridview exactly below to the corresponding Gridview Row rather than in last column of Parent Gridview.


SQL DataSource Code for Parent GridView :

  1: <asp:SqlDataSource ID="SqlDataSource1" runat="server"
  2: SelectCommand="SELECT TOP (10) OrderID, CustomerID, EmployeeID, ShipName as Name,
  3: ShipAddress as Address, ShipCity as City, ShipRegion as Region, ShipPostalCode as Postal,
  4: ShipCountry as Country FROM Orders"
  5: ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>">
  6: </asp:SqlDataSource>

Child GridView Code :

  1: <asp:GridView ID="gvDetails" runat="server" CellPadding="4" ForeColor="#333333" GridLines="Both"
  2:                                             DataSourceID="SqlDataSource2" Style="position: relative" AutoGenerateColumns="False">
  3: <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
  4: <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
  5: <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
  6: <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
  7: <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
  8: <EditRowStyle BackColor="#999999" />
  9: <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
 10: <Columns>
 11:  <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
 12:  <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
 13:  <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
 14:  <asp:BoundField DataField="Quantity" HeaderText="Quantity" SortExpression="Quantity" />
 15:  <asp:BoundField DataField="Discount" HeaderText="Discount" SortExpression="Discount" />
 16:  <asp:BoundField DataField="CompanyName" HeaderText="CompanyName"  SortExpression="CompanyName" />
 17: </Columns>
 18: </asp:GridView>

SQL DataSource Code for Child GridView
  1: <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
  2: SelectCommand="SELECT C.CompanyName, OD.UnitPrice, OD.Quantity, OD.Discount, E.FirstName, E.LastName, OD.OrderID, C.CustomerID, E.EmployeeID FROM  dbo.[Order Details] AS OD INNER JOIN
  3: dbo.Orders AS O ON OD.OrderID = O.OrderID INNER JOIN
  4: dbo.Customers AS C ON O.CustomerID = C.CustomerID INNER JOIN
  5: dbo.Employees AS E ON O.EmployeeID = E.EmployeeID AND O.OrderID LIKE @OrderId AND C.CustomerID = @CustomerID AND
  6: E.EmployeeID = @EmployeeId">
  7: <SelectParameters>
  8:   <asp:Parameter Name="OrderId" />
  9:   <asp:Parameter Name="CustomerId" />
 10:   <asp:Parameter Name="EmployeeId" />
 11: </SelectParameters>
 12: </asp:SqlDataSource>

We’ll supply OrderId, CustomerID, EmployeeID to SQL DataSource of ChildGridView in RowDataBound of Parent GridView.
Parent GridView Event Handlers
C#
  1: protected void gvOrders_RowCreated(object sender, GridViewRowEventArgs e)
  2: {
  3:    if (e.Row.RowType == DataControlRowType.Header || e.Row.RowType == DataControlRowType.DataRow)
  4:    {
  5:       e.Row.Cells[1].Visible = false;
  6:       e.Row.Cells[2].Visible = false;
  7:       e.Row.Cells[3].Visible = false;
  8:    }
  9: }

VB
  1: Protected Sub gvOrders_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvOrders.RowCreated
  2:   If e.Row.RowType = DataControlRowType.Header Or e.Row.RowType = DataControlRowType.DataRow Then
  3:      e.Row.Cells(1).Visible = False
  4:      e.Row.Cells(2).Visible = False
  5:      e.Row.Cells(3).Visible = False
  6:   End If
  7: End Sub
C#
  1: protected void gvOrders_RowDataBound(object sender, GridViewRowEventArgs e)
  2: {
  3:   if (e.Row.RowType == DataControlRowType.Header)
  4:   {
  5:     e.Row.Cells[1].Visible = false;
  6:     e.Row.Cells[2].Visible = false;
  7:     e.Row.Cells[3].Visible = false;
  8:   }
  9:   if (e.Row.RowType == DataControlRowType.DataRow)
 10:   {        
 11:     SqlDataSource s = (SqlDataSource)e.Row.FindControl("SqlDataSource2");
 12:     s.SelectParameters[0].DefaultValue= e.Row.Cells[1].Text;
 13:     s.SelectParameters[1].DefaultValue = e.Row.Cells[2].Text;
 14:     s.SelectParameters[2].DefaultValue = e.Row.Cells[3].Text;
 15:
 16:     ((Label)e.Row.FindControl("lblSign")).Text = "+";
 17:     ((Label)e.Row.FindControl("lblSign")).Attributes["onclick"] = "HideShowDiv('div" + e.Row.Cells[1].Text + "', '" + ((Label)e.Row.FindControl("lblSign")) .ClientID + "');";
 18:     e.Row.Cells[0].Attributes["onmouseover"] = "this.style.cursor='pointer'";
 19:     e.Row.Cells[0].Attributes["onmouseout"] = "this.style.cursor='pointer'";
 20:         
 21:   }
 22: }

JavaScript
  1:  function HideShowDiv(DivId,LblSign)
  2:  {
  3:       var mydiv= document.getElementById(DivId);
  4:       var LblSign=document.getElementById(LblSign);
  5:       if(mydiv!=null && LblSign!=null)
  6:       {
  7:             if(mydiv.style.display!="block")
  8:            {
  9:                 mydiv.style.display="block";
 10:                 LblSign.innerHTML="-";
 11:            }
 12:            else
 13:           {
 14:                 mydiv.style.display="none";
 15:                 LblSign.innerHTML="+";
 16:           } 
 17:       }
 18:  }

Above JavaScript function will Hide/ Show Div and changes Sign of Parent Row on expansion of Div and so on. I hope this helps!! :)

Next Time i will write “How to generate Child Gridview Dynamically” :)

Enjoy!!

2 comments:

Bhaskar said...

I have seen lot of members are asked about nested grid view.This will surely helpful to all.
Thanks for nice post

Naseer's said...

please help me in updating in nested gridview,i worked on it it working on my place,but the problem is after raising any event nested grid is collapsing with master grid,every time i have to press - symbol to see data,help me to show the nested grid after the event occurs.