Wrox Press
ASPToday
       1063 Articles
  in the Solutions Library
  Log off
 
 
 
ASPToday Subscriber's Article Oscar Peli
Working with TreeView WebControl Part 1 – Basics
by Oscar Peli
Categories: .NET Framework
Article Rating: 4.5 (14 raters)
Published on September 2, 2002
 
Content Related Links Discussion Comments Index Entries Downloads
 
Abstract
One of the new gifts from .NET is Internet Explorer WebControls Version 1.0 of the ASP.NET Server Controls. This is a suite of “rich” controls that lets you deal easily with structures like TreeView, ToolBar, TabControl and Multipage that previously needed a lot of work to be developed.

In this three-part article Oscar Peli will describe one of these rich controls: TreeView. In this first part he will introduce you to the basics of this rich control. You will see your first TreeView built in a declarative mode and some other more complex samples; you will see also how to build a TreeView programmatically.

The second and third part of this article are focused on more advanced features of this control: handling events (Part 2) and data binding (Part 3).
 
 
Article

Introduction

The TreeView is one of the most useful structures in web development. In this first part of my article I want to introduce to you a wonderful control that Microsoft released for the .NET Framework. Here you have a control with a rich Object Model that lets you program various aspects by simply defining the value of some properties, or by declaring some elements.

Download and Install WebControls

Before reading this article it will be useful if you have downloaded and installed Microsoft Internet Explorer WebControls Version 1.0 of the ASP.NET Server Controls from http://msdn.microsoft.com/downloads/samples/internet/asp_dot_net_servercontrols/webcontrols/Default.asp?WROXEMPTOKEN=2440221ZO0np8M1JqrR62zGgTp.

From the dropdown list "WebControls Version 1.0 Installation Options " choose "Automatic Install: WebControls Version 1.0 Client DHTML Behaviors and Server Controls ".

Wait until the browser prompts you to save or execute the file (iewebcontrols.msi), then save it on your hard disk and execute it.

At the end of installation, you can see in the Programs menu, which can be accessed from the Start button, the "Microsoft Internet Explorer WebControls " entry. There you can find a shortcut to the IE WebControls MSDN documentation and a readme file where you can read the step by step installer operations.

The Simplest TreeView

The first sample of a TreeView is a very simple program, the source code for it can be found in the FirstTree.aspx file in the support material of this article. I won't describe everything, but I will describe the lines that are directly concerned with the TreeView control.

The first line is an @Import directive for the WebControls. This explicitly imports a namespace into the page, making all classes and interfaces of the imported namespace available. (If you want to know more on the @Import directive point your browser to http://msdn.microsoft.com/library/en-us/cpgenref/html/cpconimport.asp?WROXEMPTOKEN=2440221ZO0np8M1JqrR62zGgTp.)

<%@ import namespace="Microsoft.Web.UI.WebControls" %>

The second line is an @Register directive that associates an alias with the namespace and class name for concise notation. Including this directive in a page allows you to layout a TreeView server control using declarative TreeView syntax.

If you want to know more on the @Register directive point your browser to http://msdn.microsoft.com/library/en-us/cpgenref/html/cpconregister.asp?WROXEMPTOKEN=2440221ZO0np8M1JqrR62zGgTp.

<%@ Register TagPrefix="myfirsttree" 
Namespace="Microsoft.Web.UI.WebControls" 
Assembly="Microsoft.Web.UI.WebControls, Version=1.0.2.226, Culture=neutral, 
PublicKeyToken=31bf3856ad364e35" %>

Note that all WebControls elements must be authored inside a Form element. The runat="server" attribute has also to be specified for the Form to indicate that ASP.NET will process the results of any user input. So the TreeView element is a child of the Form and has the runat="server" attribute too.

Note the use of the tag prefix myfirsttree; this will be used for all the WebControls elements in the page since it has been predefined in the @Register directive.

<HTML>
<HEAD></HEAD>
<BODY>
<FORM runat="server">
<myfirsttree:treeview runat="server" SHOWTOOLTIP="false">

Inside the TreeView element you can insert TreeNode elements to build your structure. To produce a hierarchical structure of nodes, simply add a child TreeNode element inside his parent element.

The "smart" Text attribute

The Text attribute of the TreeNode element is the label of the node; you can apply HTML tags directly to the Text attribute both to customize the appearance of the label and to associate smart functions with the node.

In the FirstTree.aspx sample I have added a ToolTip property to the node that will "overload" the default ToolTip property of the control (see the SHOWTOOLTIP="false" attribute in the TreeView definition above).

Let's look at the first node definition (not the root node); here I define the Text attribute so that the label will displayed in bold (the <b></b> tag). Inside the opening <b> tag I define two client-side event handlers: OnMouseOver and OnMouseOut; when the user hovers over the node with the mouse pointer, the JavaScript popup function will be called; when the user moves the mouse pointer out of the node, the JavaScript kill function will be called.

<myfirsttree:treenode text="<b
OnMouseOver=popup('This_is_a_normal_message@br@bThis_is_a_bold_message@@b@br
                   @iThis_is_an_italic_message@@i')
OnMouseOut=kill()>My first Tree Node</b>">
</myfirsttree:treenode>

All the code needed to manage this ToolTip property is contained inside the following block of code:

<DIV class=dek id=dek></DIV>
<STYLE type=text/css>
.DEK 
{
      POSITION: absolute; 
      VISIBILITY: hidden; 
      Z-INDEX: 200;
}
</STYLE>

<SCRIPT type=text/javascript>
<!--
Xoffset= -50;
Yoffset= 20; 
var nav,old,iex=(document.all),yyy=-1000;

// Check for Netscape browser
if(navigator.appName=="Netscape")
{
      (document.layers)?nav=true:old=true;
}

// Check for old browser
if(!old)
{
      var skn=(nav)?document.dek:dek.style;
      if(nav)document.captureEvents(Event.MOUSEMOVE);
      document.onmousemove=get_mouse;
}

// Displays the ToolTip with the input message
// NOTE: the message has a format where the HTML tags are placeholders
//       the function first substitutes the placeholders with the HTML tags
function popup(msg){
      msg = msg.replace(/_/g, " ");
      msg = msg.replace(/@br/g, "<br>");
      msg = msg.replace(/@@b/g, "</b>");
      msg = msg.replace(/@b/g, "<b>");
      msg = msg.replace(/@@i/g, "</i>");
      msg = msg.replace(/@i/g, "<i>");
      msg = msg.replace(/@@u/g, "</u>");
      msg = msg.replace(/@u/g, "<u>");
      bak='#E7F3E3';
      var content="<TABLE WIDTH=190 BORDER=1 BORDERCOLOR=#7BCEAD "+
      "CELLPADDING=2 CELLSPACING=0 BGCOLOR="+bak+"><TD ALIGN=left> "+
      "<FONT COLOR=#808080 SIZE=1 face=verdana>"+msg+"</FONT></TD></TABLE>";
      if(old)
      {
            alert(msg);
            return;
      } 
      else
      {
            yyy=Yoffset;
      if(nav){skn.document.write(content);skn.document.close();skn.visibility="visible"}
      if(iex){document.all("dek").innerHTML=content;skn.visibility="visible"}
      }
}

// Sets the position of the ToolTip
function get_mouse(e){
      stringa=/MSIE 4.0/;
      substringa=stringa.test(navigator.appVersion);
      if(substringa==true){
        var x=(nav)?e.pageX:event.x;skn.left=x+Xoffset;
        var y=(nav)?e.pageY:event.y;skn.top=y+yyy;
      }
      else {
        var x=(nav)?e.pageX:event.x+document.body.scrollLeft;skn.left=x+Xoffset;
        var y=(nav)?e.pageY:event.y+document.body.scrollTop;skn.top=y+yyy;
      }
}

// Hides the ToolTip
function kill(){
      if(!old)
      {
            yyy=-1000;
            skn.visibility="hidden";
      }
}

//-->
</SCRIPT>

The ToolTip is displayed with a <div> tag with id=dek. The first lines of code check for Netscape browsers and checks if the version of this browser supports layers. The popup function first substitutes the placeholders of HTML tags and replaces the underline character with a blank character (this is because it is not possible to insert text with blanks and tags inside the definition of the Text attribute of the TreeNode element); then this function displays an alert for those browsers that don't support layers or displays the ToolTip.

The get_mouse function retrieves the mouse position to set the position of the ToolTip. The kill function hides the ToolTip for those browsers who support layers and for Internet Explorer browsers.

Now let me show you what you see when you run the FirstTree.aspx sample; note that under the TreeView definition there is a single TreeNode element that will be the tree's root that owns three child TreeNode elements.

When you run this page you will see only the root element with a plus sign that indicates that it is expandable. Click on it to see how it expands or collapses. The following figure shows you the tree expanded.

If you move your mouse over the nodes (My first Tree Node, My second Tree Node or My third Tree Node) you see the following ToolTips:

This may be one of the simplest trees you can build, however it is possible to easily enhance it with some useful attributes of this powerful control.

Some Useful Attributes and Elements

The TreeView control has a really rich object model; here you will see some useful attributes you will use to render a tree structure in a cool way. Moreover you will use some elements that will facilitate some common tasks.

Attributes: ImageUrl, ExpandedImageUrl, SelectedImageUrl

When you create a TreeView it is possible that you want to associate an image to reflect the status of a node, for example, expanded or selected. First you have to put some gif images in the same directory of your page then you can use the ImageUrl, ExpandedImageUrl and SelectedImageUrl attributes of the TreeView element to associate an image to the normal, expanded and selected status of a node respectively.

<myfirsttree:treeview runat="server"
ImageUrl="closed.gif"
ExpandedImageUrl="closed.gif"
SelectedImageUrl="open.gif">

In the following figure you can see an example (the source code of the samples in this section is stored in the FirstTreePlusAttrs.aspx).

Element: TreeNodeType; attributes: ChildType, Type

Using the above attributes at TreeView level lets you define the appearance of all the tree's nodes. You can define these attributes also at TreeNode level, but you should understand that this is not an efficient way to operate.

To build a TreeView with advanced appearance customization you can use the TreeNodeType element to group several attributes to associate to a collection of nodes. The TreeNodeType element is used in conjunction with the ChildType attribute, so you can define the ChildType at TreeView level indicating that there is a TreeNodeType element that defines it.

The following code shows you how to define different TreeNodeType elements and how to associate them with child nodes (see FirstTreePlusTypes.aspx). In the TreeView element I define the ChildType attribute that indicates that all the child nodes will have attributes defined by a TreeNodeType element whose Type attribute is equal to "Folder ".

...
<myfirsttree:treeview runat="server" ChildType="Folder">
...

Here I define the attributes of the TreeNodeType element of type "Folder "; I define the ImageUrl, ExpandedImageUrl and SelectedImageUrl attributes and also a ChildType attribute indicating that all the child nodes will have attributes defined by a TreeNodeType element whose Type attribute is equal to "Html ".

...
<mytree:treenodetype 
Type="Folder"
ChildType="Html"
ImageUrl="closed.gif"
ExpandedImageUrl="closed.gif"
SelectedImageUrl="open.gif" />
...

Here I define the last TreeNodeType element (of Type "Html ") and I define only the ImageUrl attribute.

...
<mytree:treenodetype Type="Html" ImageUrl="html.gif" />
...

After the "type" definition there is the tree structure with three nodes at the first level that own a single node each.

...
      <myfirsttree:treenode text="My first Tree Node">
            <myfirsttree:treenode text="My first Tree Leaf">
            </myfirsttree:treenode>
      </myfirsttree:treenode>
      <myfirsttree:treenode text="My second Tree Node">
            <myfirsttree:treenode text="My second Tree Leaf">
            </myfirsttree:treenode>
      </myfirsttree:treenode>
      <myfirsttree:treenode text="My third Tree Node">
            <myfirsttree:treenode text="My third Tree Leaf">
            </myfirsttree:treenode>
      </myfirsttree:treenode>
</myfirsttree:treeview>
...

As you can see the ChildType attribute is used both in the TreeView element and in the first TreeNodeType element; the last TreeNodeType element has no ChildType because this defines the deepest type in the tree.

Attributes: DefaultStyle, HoverStyle, SelectedStyle

For uplevel browsers (Internet Explorer/Netscape version 4 or higher) you can further enhance the appearance of nodes using the DefaultStyle, HoverStyle and SelectedStyle attributes:

  • The DefaultStyle attribute sets or retrieves a value that indicates the default style for the element
  • The HoverStyle attribute sets or retrieves a value that indicates the style of the element when the user hovers the keyboard focus or mouse pointer over it
  • The SelectedStyle attribute sets or retrieves a value that indicates the style for the selected element

With each of these attributes you can define several Cascading Style Sheets (CSS) attribute/value pairs.

The syntax for defining this pairs is the same you use to define CSS in HTML pages, so you can use it to define fonts, colors, dimensions, cursor, zoom, and so on.

The FirstTreePlusStyles.aspx sample shows you the use of these attributes in a TreeNode element. The default style (so when it is not selected nor when you point the mouse on it) of the TreeNode element labeled "My first Tree Node " shows the node with a red background, a border of one pixel and black, Arial, 12pt text.

DefaultStyle="background:red;border:solid 1px;color:black;font-name:Arial;font-size:12pt"

The following figure shows how the node is displayed.

If you point your mouse on the node, it changes its color, the text becomes white and the font size increases to 14pt.

HoverStyle="color:white;font-size:14pt"

The following figure shows what happens if you pass your mouse on it:

If you select the node, rather than just hovering over it, the background changes to white and the text is displayed in red and is bold:

SelectedStyle="background:white;color:red;font-weight:bold"

As can be seen in this figure:

Attributes: SelectedNodeIndex, Expanded

As you have seen, when you first access a page, you can see only the nodes at the first level that are collapsed. If you want your tree be expanded with a particular node selected at first access, you can use the following attributes.

The Expanded attribute of the TreeNode element is a Boolean attribute that is "false " by default. If you set this attribute to "true " you can see the node expanded when you first access the page.

In the code belowyou can see some expanded nodes (see FirstTreeExpanded.aspx). First I expand the root node:

...
<myfirsttree:treenode text="Italy" Expanded="true">
      <myfirsttree:treenode text="North" Type="Folder"></myfirsttree:treenode>

Then I expand the second child node (text="Center"):

      <myfirsttree:treenode text="Center" Expanded="true" Type="Folder">
            <myfirsttree:treenode text="Toscana"></myfirsttree:treenode>
            <myfirsttree:treenode text="Emilia Romagna"></myfirsttree:treenode>
            <myfirsttree:treenode text="Marche"></myfirsttree:treenode>
            <myfirsttree:treenode text="Umbria"></myfirsttree:treenode>
            <myfirsttree:treenode text="Lazio"></myfirsttree:treenode>
      </myfirsttree:treenode>
...

Now I want the third node (text="Marche") to be selected at the first access. To do so I have to use the SelectedNodeIndex attribute of the TreeView element. The value of this attribute is the index of the TreeNode to be selected. The index is built by concatenating the ordinal number of the parent node at each level counting through the tree from 0 down to the selected node and delimiting each level with a dot (.). The uppermost node in the top level of the tree is 0; the second node is 1, and so on. The node immediately following the first top-level node is 0.0; the second is 0.1, and so on.

So in the sample the index of the "Marche " node is "0.1.2 ".

 < myfirsttree:treeview runat="server" 
SelectedNodeIndex="0.1.2"
ChildType="Folder"
SelectExpands="true">

The following figure shows what happens when you first access the page.

Note: when you use the SelectedNodeIndex attribute you must expand all the TreeNode elements so that the node to be selected can be displayed. If you forget this, your page will raise the following error:

You can test this error by deleting the Expanded attribute in the "Center " node.

<myfirsttree:treenode text="Center" Type="Folder">

Attributes: SelectExpands

In the previous code sample you will have noted that the TreeView element contain the attribute SelectExpands. When this attribute is true, the node expands and collapses when selected (and not just when you click on the "plus" or "minus" sign); you can test this on the previous example.

Build a TreeView by Code

So far we have shown you how to build a "static" TreeView using the control's declarative syntax. For some applications this approach can be enough, but for several tasks you need to build a TreeView dynamically at run time.

In most cases the structure comes from a database so you will have to deal with data binding. In this section you will learn how to build a TreeView using code; the third part of this article will describe the data bind support of TreeView control.

A typical sample of a dynamic tree structure not coming from a database is the filesystem structure. So suppose you have this directory structure:

In the support files you will find three files that lets you to build a Windows Explorer-like interface accessible via the web.

The TreeFrameset.htm file contains the frame structure of this application and the TreeFileList.aspx contains the code to display the contents of a selected directory (look at the comments inside this file to learn how it works).

The code needed to build a programmatic tree is contained in the TreeCode.aspx file; since you will build the structure using code, you have to add only the TreeView element and a root TreeNode element to your page. The rest of the structure is built by the code:

<body>
      <form id="Form1" method="post" runat="server">
            <iewc:treeview id="TreeView1" runat="server" 
            ImageUrl="closed.gif" 
            ExpandedImageUrl="closed.gif" 
            SelectedImageUrl="open.gif"
            SHOWTOOLTIP="false">
                  <iewc:TreeNode Text="_dir"
                        NavigateUrl="TreeFileList.aspx?path=C:\_dir"
                        Target="contents">
                  </iewc:TreeNode>
            </iewc:treeview>
      </form>
</body>

You need a DirectoryInfo class to collect the folders set (see the DirectoryInfo class definition at http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemIODirectoryInfoClassTopic.asp?WROXEMPTOKEN=2440221ZO0np8M1JqrR62zGgTp for details).

To use a DirectoryInfo class you need to import the namespace System.IO:

<%@ Import namespace="System.IO" %>

Let me show how the code works now. First, look at the Page_Load method; this method is invoked as the page is called. There I initialize a new instance of the DirectoryInfo class on the specified path, it exposes instance methods for creating, moving, and enumerating through directories and subdirectories of the "_dir " directory.

Then I define the Text attribute of the root node; as you can see I use the ToolTip property I defined in the first section of this article to show the number of directories and files contained in the root directory.

Finally, I call a recursive procedure to add nodes to the structure in the right position. I pass the just created object to this procedure and the root TreeNode element. To define an object that represents the root TreeNode element, I use the GetNodeFromIndex method of the TreeView object that returns the TreeNode object at the specified index, in this case the object at the "0 " index is exactly the root TreeNode element.

private void Page_Load(object sender, System.EventArgs e)
{
      DirectoryInfo dir = new DirectoryInfo("C:\\_dir\\");
      TreeView1.GetNodeFromIndex("0").Text = "<p OnMouseOver=popup
('Directories:_" + dir.GetDirectories().Length 
+ "@brFiles:_" + dir.GetFiles().Length + "') OnMouseOut=kill()>_dir</p>";      
analyzeCurrentDir(dir, TreeView1.GetNodeFromIndex("0"));
}

The analyzeCurrentDir procedure receives in input the current directory you are exploring and the TreeNode parent of the nodes you are going to add.

public void analyzeCurrentDir(DirectoryInfo dirIn, TreeNode treenodeI)
{

Here I define an array of DirectoryInfo objects that will be filled by the GetDirectories method of the DirectoryInfo object that returns the subdirectories in the specified directory. So, the subdirs variable will contain all the subdirectories in the "_dir " directory at the first call, all the subdirectories of the "_dir_1 " directory at the first recursive call, and so on.

DirectoryInfo[] subdirs;
subdirs = dirIn.GetDirectories();

For each directory of this set you have to:

  • Create a TreeNode object
  • Define some attributes of this new node
  • Attach the node to the structure; I use the Add method that adds a TreeNode to the end of the TreeView or TreeNode
  • Run the recursive procedure on this new object.

Here is the code that does this:

      foreach (DirectoryInfo dir in subdirs)
      {
            //Create a TreeNode object
            Microsoft.Web.UI.WebControls.TreeNode treenode = new TreeNode();

            FileInfo[] files;
            files = dir.GetFiles();
            //Define the label of the node
            treenode.Text = "<p  OnMouseOver=popup('Directories:_" + 
    dir.GetDirectories().Length + "@brFiles:_" + files.Length + "') 
    OnMouseOut=kill()>" + dir.Name + "</p>";
            //Define the URL of the page to navigate to when the user clicks a node
            treenode.NavigateUrl = "TreeFileList.aspx?path=" + dir.FullName;
            //Define a value that indicates the window or frame at which to 
            //target the contents
            treenode.Target = "contents";
            //Add the node at the end of the tree structure
            treenodeI.Nodes.Add(treenode);
            //Recursive call of the procedure 
            analyzeCurrentDir(dir, treenode);      }
}

In the code above I introduced two new attributes that I will explain in the next section.

Attributes: NavigateUrl, Target

After you have built a tree structure, you want of course use it in some way. In the above sample you may want to list all the directories and all the files contained in a directory simply clicking on the relative node of the tree.

The NavigateUrl attribute of the TreeNode object lets you define the URL of the page to navigate to when the user click a node. The Target attribute lets you define a value that indicates the window or frame at which to target the contents.

Put It All Together

Well, now all that I have to do is to show you what happens when you call the TreeFrameset.htm.

Conclusion

In this article, the first in a three part series, you have seen how to work with the TreeView WebControl. The first tree that you saw is a simple, but effective program and you saw how to use the Text attribute of the TreeNode element in a "smart" way.

In the rest of the article you saw some useful attributes and elements to work with, and at the end of this first part you saw how to build a tree structure by code.

In the second and third parts of my article I will show some other interesting features of the TreeView WebControl: handling events and data binding.

 

Please rate this article using the form below. By telling us what you like and dislike about it we can tailor our content to meet your needs.

Article Information
Author Oscar Peli
Chief Technical Editor John R. Chapman
Project Manager Helen Cuthill
Reviewers Andrew Krowczyk & Saurhab Nandu

If you have any questions or comments about this article, please contact the technical editor.

 
 
Rate this Article
How useful was this article?
Not useful Very useful
Brief Reader Comments: Read Comments
Your name (optional):
 
 
Content Related Links Discussion Comments Index Entries Downloads
 
Back to top