The
TreeView Web server control is used to display hierarchical data, such as a table of contents or file directory, in a tree structure. It supports the following features:
- Automatic data binding, which allows the nodes of the control to be bound to hierarchical data, such as an XML document.
- Node text that can be displayed as either selectable text or hyperlinks.
- Node population through client-side callbacks to the server (on supported browsers).
Populate nodes on demand
It might not be practical to define your data structure statically, or the data might depend on information that is gathered at run time. To display data dynamically, the
TreeView control supports dynamic node population.
When the TreeView control is configured to populate on demand, the control raises an event when a user expands the node. The event handler retrieves the appropriate data and then populates the node that the user has clicked.
To populate the TreeNode object with data on demand, set the
PopulateOnDemand property of a node to true, and create a TreeNodePopulate event handler to populate the TreeNode object with data.
When populate a large number of nodes on demand, it will take some time for the servers to respond. Ideally in client side, a waiting cusor needs to be displayed to inform the client users to wait.
The following page shows how to display the waiting cursor when users click one of the nodes to populate their child nodes.
The important point in the page is the
LinksTreeView.Attributes.Add("onclick", "javascript:return treeNodeClicked(event, '')"); which add a client function to the tree.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile = "~/testTree2.aspx.cs" Inherits ="testTree2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>TreeView PopulateNodesFromClient Example</title>
<script type="text/javascript" language="javascript" src="../script/library.js"></script>
</head>
<body>
<form id="form1" runat="server">
<h3>TreeView PopulateNodesFromClient Example</h3>
<asp:TreeView id="LinksTreeView"
Font-Names= "Arial"
ForeColor="Blue"
EnableClientScript="true"
PopulateNodesFromClient="true"
OnTreeNodePopulate="PopulateNode" ExpandDepth = "0"
runat="server">
<Nodes>
<asp:TreeNode Text="Inventory"
SelectAction="Expand"
PopulateOnDemand="true"/>
</Nodes>
</asp:TreeView>
<br /><br />
<asp:Label id="Message" runat="server"/>
</form>
</body>
</html>
C# Code behind
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class testTree2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
LinksTreeView.Attributes.Add("onclick", "javascript:return treeNodeClicked(event, '')");
}
protected void PopulateNode(Object sender, TreeNodeEventArgs e)
{
// Call the appropriate method to populate a node at a particular level.
switch (e.Node.Depth)
{
case 0:
// Populate the first-level nodes.
PopulateCategories(e.Node);
break;
case 1:
// Populate the second-level nodes.
PopulateProducts(e.Node);
break;
default:
// Do nothing.
break;
}
}
protected void PopulateCategories(TreeNode node)
{
// Query for the product categories. These are the values
// for the second-level nodes.
DataSet ResultSet = RunQuery("Select CategoryID, CategoryName From Categories");
// Create the second-level nodes.
if (ResultSet.Tables.Count > 0)
{
// Iterate through and create a new node for each row in the query results.
// Notice that the query results are stored in the table of the DataSet.
foreach (DataRow row in ResultSet.Tables[0].Rows)
{
// Create the new node. Notice that the CategoryId is stored in the Value property
// of the node. This will make querying for items in a specific category easier when
// the third-level nodes are created.
TreeNode newNode = new TreeNode();
newNode.Text = row["CategoryName"].ToString();
newNode.Value = row["CategoryID"].ToString();
// Set the PopulateOnDemand property to true so that the child nodes can be
// dynamically populated.
newNode.PopulateOnDemand = true;
// Set additional properties for the node.
newNode.SelectAction = TreeNodeSelectAction.Expand;
// Add the new node to the ChildNodes collection of the parent node.
node.ChildNodes.Add(newNode);
}
}
}
protected void PopulateProducts(TreeNode node)
{
// Query for the products of the current category. These are the values
// for the third-level nodes.
DataSet ResultSet = RunQuery(""Select ProductName From Products Where CategoryID="" + node.Value);
// Create the third-level nodes.
if (ResultSet.Tables.Count > 0)
{
// Iterate through and create a new node for each row in the query results.
// Notice that the query results are stored in the table of the DataSet.
foreach (DataRow row in ResultSet.Tables[0].Rows)
{
// Create the new node.
TreeNode NewNode = new TreeNode(row["ProductName"].ToString());
// Set the PopulateOnDemand property to false, because these are leaf nodes and
// do not need to be populated.
NewNode.PopulateOnDemand = false;
// Set additional properties for the node.
NewNode.SelectAction = TreeNodeSelectAction.None;
// Add the new node to the ChildNodes collection of the parent node.
node.ChildNodes.Add(NewNode);
}
}
}
protected DataSet RunQuery(String QueryString)
{
// Declare the connection string. This example uses Microsoft SQL Server
// and connects to the Northwind sample database.
String ConnectionString = "server=localhost;database=NorthWind;Integrated Security=SSPI";
SqlConnection DBConnection = new SqlConnection(ConnectionString);
SqlDataAdapter DBAdapter;
DataSet ResultsDataSet = new DataSet();
System.Threading.Thread.Sleep(2000);
try
{
// Run the query and create a DataSet.
DBAdapter = new SqlDataAdapter(QueryString, DBConnection);
DBAdapter.Fill(ResultsDataSet);
// Close the database connection.
DBConnection.Close();
}
catch (Exception ex)
{
// Close the database connection if it is still open.
if (DBConnection.State == ConnectionState.Open)
{
DBConnection.Close();
}
Message.Text = "Unable to connect to the database.";
}
return ResultsDataSet;
}
}
Javascrip file library.js for include:
function treeNodeClicked(eventObj, strText)
{
var elementObj;
var refObj;
var PopulateHref = "javascript:TreeView_PopulateNode(";
// Internet Explorer
if (eventObj.srcElement)
{
elementObj = eventObj.srcElement;
}
// Netscape and Firefox
else if (eventObj.target)
{
elementObj = eventObj.target;
}
if (elementObj == undefined)
{
return;
}
if (elementObj.tagName == 'A' || elementObj.tagName == 'a')
{
refObj = elementObj;
}
else
{
//If it is the image in , we need to get the parent tag
if (elementObj.parentNode.tagName == 'A' || elementObj.parentNode.tagName == 'a')
{
refObj = elementObj.parentNode;
}
}
if (refObj != undefined)
{
if (refObj.href.substring(0, PopulateHref.length) == PopulateHref)
{
refObj.style.cursor = 'wait';
window.setTimeout("ChangeCursor('" + refObj.id + "')", 2000);
}
}
}
function ChangeCursor(strItemId)
{
var ToggleHref = "javascript:TreeView_ToggleNode";
var refObj = document.getElementById(strItemId);
if (refObj.href.substring(0, ToggleHref.length) == ToggleHref)
{
refObj.style.cursor = 'default';
}
else
{
window.setTimeout("ChangeCursor('" + strItemId + "')", 2000);
}
}