Click here to Skip to main content
Click here to Skip to main content

Creating a highly manageable TreeView control using Microsoft Web TreeView control

, 20 Sep 2005
Rate this:
Please Sign up or sign in to vote.
An atricle on how to implement a manageable treeview architecture.

Introduction

We all know the power of Microsoft Management Console (MMC). MMC is Microsoft’s standard platform for administrative and system management tools. MMC lets you use snap-ins to manage every part of Windows and even other applications from the same standard interface. The purpose of this article is to provide a MMC like interface over the web (I call it MMC Web). MMC Web represents a common view point to a variety of administrative tasks, which will make life more easy. MMC Web is made on an easy attachable framework that will let users to add / remove modules as well as reuse them over time with less hassle.

Requirements

The code has been written using Microsoft Web TreeView control, therefore the scripts to be run to render the tree should be in their proper place. The scripts are provided in the download, under the tools folder. To make sure that the tree view works properly, all you need to do is to copy the webctrl_client folder to your IIS wwwroot directory.

Using the code

Now, assume that we want to represent a simple organizational hierarchy. To dig a little deeper, assume that there is a company, under it there are some departments, and every department is composed of some sections. In a more technical fashion, there are three entities Company, Department and Section, where departments are children of the company and sections are children of a department. Now, to achieve this form of structure in a tree, the simplest steps are:

  1. Implementing the IProvider interface: create object specific provider classes (e.g. CompanyProvider). These classes will be responsible for fetching data from the data source for a specific ID. The ID will be provided internally by the framework according to the hierarchy defined in the XML schema.
  2. Implementing the IRenderer interface: create object specific renderer classes (e.g. CompanyRenderer). These classes will provide the rendering option for the tree, like how the tree will be rendered.
  3. Construct an XML that will define the relationships among the objects and their behaviour type.

    The XML format is as shown below:

    <company assembly="TreeView.Objects" 
             provider="TreeView.Objects.Provider.CompanyProvider" 
             renderer="TreeView.Objects.Renderer.CompanyRenderer" 
             expanded = "true" >
        <department assembly="TreeView.Objects" 
               provider="TreeView.Objects.Provider.DepartmentProvider" 
               renderer="TreeView.Objects.Renderer.DepartmentRenderer" 
               expanded = "true" >
           <section assembly="TreeView.Objects" 
                provider="TreeView.Objects.Provider.SectionProvider" 
                renderer="TreeView.Objects.Renderer.SectionRenderer" 
                expanded = "false"/>
        </department>
    </company >

    Each XML node contains a few attributes which are:

    1. assembly
      • defines where the renderers, providers and objects could be found.
    2. provider
      • defines the object type of the provider class.
    3. renderer
      • defines the object type of the renderer class.
    4. expanded
      • defines the status of the tree node.

    All these attributes are used to build the object model dynamically from the XML.

  4. Finally, we need to drag the ExtendedTreeView control (the wonder control) to a web page and call the LoadXml function with the proper server path at page load.

Once the loading is complete we then need the proper entity ID at each selection change, using which we will load the entity information at the right side of the tree. During construction, each tree node ID is internally constructed by an '_' separated ID and an object name format by the treeview framework, which does solve our problem. At selection, we just need to manage to get the proper tree node object from the '.' separated string node ID.

private void treeView_SelectedIndexChange(object sender, 
            Microsoft.Web.UI.WebControls.TreeViewSelectEventArgs e)
{
    // gets the node id in dot separated format.
    _NodeID = e.NewNode;
    // load
    LoadPage( _NodeID );
}

Now, to show the entity detail, we can create controls for entity names (example: company.ascx). To make the loading of different entities possible in the most uniform way, each control needs to extend a BaseControl class and implement an IHost interface. The interface will make the control pluggable to the treeview framework, as on each selection change from the first part of the node ID, we load the control and load the entity information using the second part of the node string with the help of the IHost interface.

private void LoadPage( string nodeID  )
{
    BaseControl control = null;
    // this line does all tricks of geting  real from dot separated node ID
    TreeNode node = treeView.GetNodeFromIndex( nodeID );
    // make the id
    string[] nodeParts =  node.ID.Split( '_' );
    //save the ids
    _PropertyID = Int32.Parse(  nodeParts[ 1 ] );
    _ControlID = nodeParts[ 0 ];

    control = ( BaseControl ) pnlRenderer.FindControl( _ControlID );

    if( control == null )
    {
        // get the control name
        string controlName = "Controls/" + nodeParts [ 0 ] + ".ascx";
        //Control control =  LoadControl( controlName );
        control = ( BaseControl ) LoadControl( controlName );
        control.ID = _ControlID; 

        if ( control != null )
        {
            pnlRenderer.Controls.Clear();
            pnlRenderer.Controls.Add( control );
            // bind the events
            control.PreRender +=new EventHandler(control_PreRender);
            control.OnChange+=new OnChangeEvent(control_OnChange);
        }
    }//if( control == null )

    IHost loader = ( IHost ) control; 
    // load the module
    if ( nodeID != String.Empty )
    {
        loader.LoadTab( _PropertyID );
    }
}

About the framework

As far as we have seen, the treeview uses a simple XML file to build its object model. Now, let's look in a little deeper and see how the job is really done. The treeview framework uses a control named extendedTreeView that has been built on the Microsoft Web TreeView control. It extends all the functionalities of the existing TreeView control. In addition it gives a function that is the heart of building a tree in the most friendly fashion.

public void LoadTree( string ServerPath );

As you can see, the function expects a server path for the XML file that contains the definition of the tree structure. Once the path is provided, it loads an object model recursively from the XML.

Part of the source follows:

private Defination FillObject( XmlNode rootNode )
{
    Assembly ass =  Assembly.Load(  rootNode.Attributes["assembly"].Value );

    Defination def = new Defination();
    // create the provider object
    object providerObject = 
      Activator.CreateInstance( ass.GetType( 
      rootNode.Attributes["provider"].Value, true ) );
    def.Provider = ( Interface.IProvider ) providerObject;
    // create the renderer object
    object rendererObject = 
      Activator.CreateInstance( ass.GetType( 
      rootNode.Attributes["renderer"].Value, true ) );
    def.Renderer = ( Interface.IRenderer ) rendererObject;
    // will the node be expanded
    def.IsExpanded = bool.Parse( rootNode.Attributes["expanded"].Value );
    return def; 
}

After it is done constructing the object from the XML file, it then uses the model to build up a tree structure. The process is to start constructing the tree from the root node and then go down from the highest level until the leaf is encountered.

public void LoadTree( string serverPath )
{
    Schema schema = new Schema( serverPath );
    Defination defination = schema.RootNode;
    ExecuteDef( defination, 0 , null );
}
private void ExecuteDef( Defination defination, 
                         int parentID, TreeNode parentNode  )
{
    IProvider provider = defination.Provider;
    IList list =  provider.GetAll( parentID );
    LoadList( list, defination, parentID, parentNode );
}

private void LoadList( IList list, Defination def, 
                       int parentNodeID, TreeNode parentNode  )
{
    foreach( object obj in list )
    {
        IRenderer renderer = def.Renderer;
        renderer.Set( obj );
        TreeNode node = ConstructNode( renderer, parentNodeID );
        PopulateNode( node, parentNodeID, parentNode );
        if( def.IsExpanded )
        {
            LoadNode( renderer, def, node );
        }
    }// end foreach
}

Finally

MMC Web will help users to reduce the number of lines of code by reusing the most common set of modules (Ex. password change, add new registration, and many more) which are already written by someone else. Thus it will help ISVs grow better.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mehfuz Hossain
Software Developer Telerik Corporation
Bangladesh Bangladesh
Passionate about cutting edge technologies and a .net enthusiast. I have played roles in variety of products starting from University automation to web 2.0 start-page (www.pageflakes.com).
 
Currently, working at Telerik Inc (www.telerik.com), the premium rad control provider for asp.net and winforms. I am a active contributor and member at www.dotnetslackers.com. In addition, i do a frequent post on my blog about LINQ, C#, Asp.net and about my projects.
 
I am Microsoft MVP. I love to travel and meet cool people.

Comments and Discussions

 
QuestionTreeView.Objects.dll and TreeView.Design.dll [modified] Pinmemberothmane20113-Feb-10 1:41 
QuestionTreeview PinmemberCh.Gayatri Subudhi19-Mar-09 22:22 
Questionneed your advice Pinmemberhafidz4-Sep-08 15:34 
AnswerRe: need your advice PinmemberMehfuz Hossain5-Sep-08 5:43 
Generalcoding Extended TreeView PinmemberPhan Thanh Lam10-Mar-08 5:20 
I want when i check parent node, child node will check.This is my codes( I like javascript coding for this event but i can't code)
html:
<cc1:extendedtreeview id="et" style="Z-INDEX: 109; LEFT: 352px; POSITION: absolute; TOP: 248px" runat="server" width="304px" height="72px" expandlevel="1" selectexpands="True" autoselect="True">

vb code:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not Page.IsPostBack Then
filltree()
End Sub
Function filltree()
Dim sql, sql1 As String
sql = "select * from pt"
Dim dts As New DataSet
Dim path As New ketnoidulieu
Dim sqlConn As New SqlConnection(path.path)
Dim sqlDa = New SqlDataAdapter(sql, sqlConn)
sqlDa.fill(dts, sql)
Dim mang As ArrayList
mang = layKetqua_R1(dts, 1)
Dim i, j As Int16
Dim mang1 As ArrayList
Dim test As String
Dim nut As New Button
For i = 0 To dts.Tables(0).Rows.Count - 1
Dim node As New TreeNode
node.Text = dts.Tables(0).Rows(i).Item(1)
node.ID = dts.Tables(0).Rows(i).Item(0)
node.NavigateUrl = ""
node.CheckBox = True
sql1 = "select * from nhansu_to where ms_pt='" & dts.Tables(0).Rows(i).Item(0) & "'"
Dim dts1 As New DataSet
Dim sqlDa1 = New SqlDataAdapter(sql1, sqlConn)
sqlDa1.fill(dts1, sql1)
For j = 0 To dts1.Tables(0).Rows.Count - 1
Dim child As New TreeNode
child.Text = dts1.Tables(0).Rows(j).Item(1)
child.ID = dts1.Tables(0).Rows(j).Item(0)
child.NavigateUrl = ""
child.CheckBox = True
child.Checked = node.Checked
node.Nodes.Add(child)
Next
et.Nodes.Add(node)
et.SelectExpands = True
test = test + dts.Tables(0).Rows(i).Item(0) + ","
 
Next
End Function
 
Lam thank you!I hope you sucessful

Generalevent checked in Extended Treeview VB.net 2003 using Javascript PinmemberPhan Thanh Lam9-Mar-08 15:51 
GeneralRe: event checked in Extended Treeview VB.net 2003 using Javascript PinmemberMehfuz Hossain9-Mar-08 20:02 
Generalcheckbox in ExtendedTreeview! PinmemberPhan Thanh Lam3-Oct-07 23:34 
GeneralRe: checkbox in ExtendedTreeview! PinmemberMehfuz Hossain4-Oct-07 6:11 
GeneralRe: checkbox in ExtendedTreeview! PinmemberPhan Thanh Lam7-Oct-07 2:09 
GeneralRe: checkbox in ExtendedTreeview! PinmemberMehfuz Hossain7-Oct-07 7:56 
Generalextendedtreeview PinmemberPhan Thanh Lam23-Sep-07 4:33 
Generalregarding treeview Pinmemberhaasini11-May-07 20:33 
GeneralRe: regarding treeview PinmemberMehfuz Hossain11-May-07 21:12 
Questiontreeview control? PinmemberPhan Thanh Lam6-Mar-07 15:07 
AnswerRe: treeview control? PinmemberMehfuz Hossain10-Mar-07 7:58 
QuestionHow to build a tree with dynamic construct Pinmemberchufall6-Oct-05 20:42 
AnswerRe: How to build a tree with dynamic construct PinmemberMehfuz Hossain11-Oct-05 22:25 
QuestionCan it be used in windows forms Pinmemberlols20-Jul-05 0:58 
AnswerRe: Can it be used in windows forms PinmemberJerry Maguire20-Sep-05 22:18 
AnswerRe: Can it be used in windows forms PinsussAnonymous21-Sep-05 0:11 
GeneralXPathNavigator PinmemberWiebe Tijsma21-Jun-05 4:11 
GeneralRe: XPathNavigator PinmemberMehfuz Hossain24-Jun-05 18:54 
GeneralGoo tech, poorly presented PinmemberOmar Al Zabir20-Jun-05 22:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.140721.1 | Last Updated 20 Sep 2005
Article Copyright 2005 by Mehfuz Hossain
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid