|
In this article I am going to
demonstrate on how to make a hierarchical GridView which enables the user to open
up the hierarchy with the click on a row, which enables the user to close the currently
opened hierarchy when the user clicks on another row or the same row. Unlike the
hierarchical grids which place a Plus or Minus sign to open and close the hierarchy,
we will create this GridView without using them (i.e., the user will be able to
just click the row and open up the hierarchy).
So let's get it started.
The features this GridView provides
are:
1. Hierarchy without plus and
minus signs.
2. Opens up the hierarchy on the
click of a row.
3. Upon clicking another row,
the currently opened hierarchy is closed and the clicked row's hierarchy is opened.
4. Upon clicking the row which
has its hierarchy already opened, the hierarchy is closed.
Before you start reading the article,
Click here to view the demo. Tested on Microsoft
Internet Explorer 6, 7, Google Chrome 1.0, Mozilla Firefox 3.0.
Now that you have seen the demo
let's create a hierarchical GridView.
In this article I'll make use of
four tables from the Northwind database, Customers, Products, Orders and Order Details.
The parent GridView will be bound to the customers table. The query which retrieves
all the customers is as shown below:
"select CustomerID,
CompanyName, Address, City, Country, Phone from Customers";
The child GridView displays all
the orders placed by each customer. The child GridView's data binding query is as
follows:
"select Products.Productname,
Products.UnitPrice, [Order Details].Quantity, [Order Details].Discount from Products
inner join [Order Details]"
+
"on Products.ProductID=[Order
Details].ProductID"
+
" where orderid
in(select orderid from orders where customerid='ALFKI')";
As the data binding queries are
ready, let's add a GridView to the aspx page as shown below:
<asp:GridView
ID="gvCustomers"
runat="server"
AutoGenerateColumns="false"
Width="100%"
ShowFooter="false" Font-Names="Verdana" Font-Size="Small"
OnRowDataBound="gvCustomers_RowDataBound">
</asp:GridView>
Pay attention to the bolded parts,
AutoGenerateColumns is set to false and we
also need to handle the OnRowDataBound event
to populate the child GridView.
Now lets add the bound fields to
display the customer information. After adding the bound fields the GridView looks
as shown below:
<asp:GridView
ID="gvCustomers"
runat="server"
AutoGenerateColumns="false"
Width="100%"
ShowFooter="false" Font-Names="Verdana" Font-Size="Small" OnRowDataBound="gvCustomers_RowDataBound">
<HeaderStyle HorizontalAlign="Left" BackColor="#000000" ForeColor="white" />
<RowStyle BackColor="" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="CustomerID"
HeaderText="Customer
ID" />
<asp:BoundField DataField="CompanyName"
HeaderText="Company Name"
/>
<asp:BoundField DataField="Address"
HeaderText="Address"
/>
<asp:BoundField DataField="City"
HeaderText="City"
/>
<asp:BoundField DataField="Country"
HeaderText="Country"
/>
<asp:BoundField DataField="Phone"
HeaderText="Phone"
/>
</Columns>
</asp:GridView>
With this the parent GridView part
(to which all the customers are bound) is finished, Now, we need to create a child
GridView to show the orders placed by each customer. For this we need to add a TemplateField
which holds the nested GridView. After adding the Template Field the entire GridView
looks as shown below:
<asp:GridView
ID="gvCustomers"
runat="server"
AutoGenerateColumns="false"
Width="100%"
ShowFooter="false" Font-Names="Verdana" Font-Size="Small" OnRowDataBound="gvCustomers_RowDataBound">
<HeaderStyle HorizontalAlign="Left" BackColor="#000000" ForeColor="white" />
<RowStyle BackColor="" ForeColor="Black" />
<Columns>
<asp:BoundField DataField="CustomerID"
HeaderText="Customer
ID" />
<asp:BoundField DataField="CompanyName"
HeaderText="Company Name"
/>
<asp:BoundField DataField="Address"
HeaderText="Address"
/>
<asp:BoundField DataField="City"
HeaderText="City"
/>
<asp:BoundField DataField="Country"
HeaderText="Country"
/>
<asp:BoundField DataField="Phone"
HeaderText="Phone"
/>
<asp:TemplateField>
<ItemTemplate>
</td></tr>
<tr>
<td colspan="6">
<div id="<%# Eval("CustomerID")
%>" style="display: none; position: relative">
<center style="color: #EF3A44">
<aspLabel ID="lblOrders" runat="server" Text="" Width="100%"></asp:Label></center>
<asp:GridView ID="gvOrders"
runat="server"
AutoGenerateColumns="false"
Width="100%"
Font-Names="Verdana"
Font-Size="small"
EmptyDataText="No orders
placed.">
<HeaderStyle HorizontalAlign="Left" BackColor="#F79196" ForeColor="black" />
<RowStyle BackColor="white" ForeColor="black" />
<AlternatingRowStyle BackColor="#FDEAEB" ForeColor="black" />
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product" />
<asp:BoundField DataField="UnitPrice" HeaderText="Unit Price" />
<asp:BoundField DataField="Quantity" HeaderText="Quantity" />
<asp:BoundField DataField="Discount" HeaderText="Discount" />
</Columns>
</asp:GridView>
</div>
</td>
</tr>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The bolded part is where the TemplateField
starts. Notice that we have used </td></tr>
and then opened a new row using <tr>. This is required because
if you do not use </td></tr>
then the nested GridView appears as the column of the parent GridView (which
is not desired). As we have closed a table row and opened a new one the nested GridView
displays in a new Row.
Now the following line of code is
where we show and hide the hierarchy:
<div id="<%#
Eval("CustomerID") %>"
style="display: none; position: relative">
Within this div tag we have created
the child GridView 'gvOrders'. The div tag's id is set to the id of the customer,
a unique id which guarantees a distinct id to each div. Initially, we set its style
display property to none, which means initially the parent GridView with list of
customers will only be visible. The nested GridView will only be visible when the
user clicks on a row. We will register the onclick event on each row in the code
behind shortly.
Now that we have completed the
aspx part, lets bind the data in the code behind part. The entire code behind part
is as shown below:
SqlConnection connection =
new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["conString"]);
protected void
Page_Load(object sender,
EventArgs e)
{
if (!IsPostBack)
{
//Call GetCustomersAndOrders() method to populate the Parent GridView.
GetCustomersAndOrders();
}
}
protected void
GetCustomersAndOrders()
{
string strCustomers
= "select CustomerID, CompanyName, Address, City,
Country, Phone from Customers";
SqlCommand
cmdCustomers = new SqlCommand(strCustomers,
connection);
SqlDataAdapter
adpCustomers = new SqlDataAdapter(cmdCustomers);
DataTable
dtCustomers = new DataTable("Customers");
adpCustomers.Fill(dtCustomers);
gvCustomers.DataSource
= dtCustomers;
gvCustomers.DataBind();
gvCustomers.GridLines
= GridLines.None;
}
protected void
gvCustomers_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType
== DataControlRowType.DataRow)
{
e.Row.Attributes.Add("onmouseover",
"this.style.backgroundColor='#4A4A4A'; this.style.cursor='pointer';
this.style.color='white'");
e.Row.Attributes.Add("onmouseout",
"this.style.backgroundColor='#FFFFFF'; this.style.color='black'");
e.Row.ToolTip = "Click to view
the orders placed by " + e.Row.Cells[1].Text;
string
strOrders = "select Products.Productname, Products.UnitPrice,
[Order Details].Quantity, [Order Details].Discount from Products inner join [Order
Details]" +
"on Products.ProductID=[Order
Details].ProductID"
+
" where orderid
in(select orderid from orders where customerid='" + e.Row.Cells[0].Text + "')";
GridView gvOrders = (GridView)e.Row.FindControl("gvOrders");
Label lblOrders = (Label)e.Row.FindControl("lblOrders");
if
(gvOrders != null)
{
SqlCommand cmdOrders =
new SqlCommand(strOrders, connection);
SqlDataAdapter adpOrders =
new SqlDataAdapter(cmdOrders);
DataTable dtOrders =
new DataTable("Orders");
adpOrders.Fill(dtOrders);
gvOrders.DataSource = dtOrders;
gvOrders.DataBind();
gvOrders.GridLines = GridLines.None;
}
if
(lblOrders != null)
{
lblOrders.Text =
"Orders placed by " + e.Row.Cells[1].Text;
}
e.Row.Attributes.Add("onclick",
"javascript:CollapseExpand('" + e.Row.Cells[0].Text
+ "')");
}
}
The GetCustomersAndOrders method
binds the data to the parent GridView with list of all customers. In the RowDataBound
event (which fires for each row) of the parent GridView('gvCustomers'), we are adding
the onmouseover and onmouseout events to change the pointer and row's background
and foreground colors.
e.Row.Attributes.Add("onmouseover",
"this.style.backgroundColor='#4A4A4A'; this.style.cursor='pointer';
this.style.color='white'");
e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor='#FFFFFF';
this.style.color='black'");
Similarly, we add the tool tip for
each row in the following line:
e.Row.ToolTip =
"Click to view the orders placed by " + e.Row.Cells[1].Text;
Finally we find the GridView and
the label control in the following lines:
GridView gvOrders = (GridView)e.Row.FindControl("gvOrders");
Label lblOrders = (Label)e.Row.FindControl("lblOrders");
Atlast we add the onclick client
side event to each row as shown below:
e.Row.Attributes.Add("onclick",
"javascript:CollapseExpand('" + e.Row.Cells[0].Text
+ "')");
The CollapseExpand(object) method
is the client side method which gets called on each click on a GridView's row. The
method is as shown below:
<script language="JavaScript" type="text/javascript">
var currentlyOpenedDiv="";
function CollapseExpand(object)
{
var div=document.getElementById(object);
if(currentlyOpenedDiv!="" && currentlyOpenedDiv!=div)
{
currentlyOpenedDiv.style.display="none";
}
if(div.style.display=="none")
{
div.style.display="inline";
currentlyOpenedDiv=div;
}
else
{
div.style.display="none";
}
}
</script>
With this we complete the creation of a hierarchical GridView. Please post
your valuable comments.
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
Name:
|
|
|
Posted On:
|
|
|
Subject:
|
|
Comments:
|
|
|
|
Name: |
|
|
EMail: |
|
|
Subject:
|
|
|
Comments: |
|
Type the two words with a space in between:
(If the words doesn't appear(due to low connectivity) or if you are unable to recognize
them, click on Get a new challenge button adjacent to the text box.)
|
|
|
|
|