Recursively populating a TreeView controls TreeNode collection

Every now and then you come across a scenario where a Treeview control is the best solution for presenting a hierarchical view of data.  How do you populate the tree?  A recursive routine is what you are looking for perhaps (at least, I haven’t run into any other tree scenario where a recursive routine was not used). 

A recursive routine is a routine that will call itself over and over, until the end of whatever

// Create a top-level node to start things off
TreeNode tn = new TreeNode("Content Categories","0");
// Pass the new node by reference, nodes will be added as children
populateTree(cats, ref tn);
// Add the nodes to the tree
this.tvCategories.Nodes.Add(tn);
this.tvCategories.DataBind();

We start off by creating a TreeNode object.  This node will be the root of the tree, and all other nodes will be under this node. The above code will then call the routine populateTree routine and provide a List of custom category objects.  Don’t be disturbed by the ‘cats’, they are just simple model objects, and we pass the new TreeNode object in as a reference object.

When the populateTree routine ends, our tn variable will contain all the children it found in the generic cats List object.

private void populateTree(List categories, ref TreeNode tn)
{
    int currentId = int.Parse(tn.Value);
    TreeNode tnAdd = null;
    // Obtain all categories that are children to the parentId
    List childCats = categories.FindAll(
    delegate(Category cat)
    {
        return cat.ParentId == currentId;
    });
    // Iterate through our subset of nodes that are children
    // of the provided tn node
    foreach (Category c in childCats)
    {
        // Create a new node to add
        tnAdd = new TreeNode(c.Name, c.CategoryId.ToString());
        tnAdd.ToolTip = c.Description;
        // Check for children of the new node
        populateTree(categories, ref tnAdd);
        if (tnAdd != null)
            // Add the child to the node collection
            tn.ChildNodes.Add(tnAdd);
    }
}

The populateTree routine begins by grabbing the current id value off the provided node.  Keeping in mind that this routine calls itself, grabbing the id tells us the node to apply the children nodes we are about to create.  The code continues by defining a null TreeNode object as well.

The first thing we are going to do is find any children within our data source.  I chose to use an anonymous delegate to make that determination in conjunction with the Generic List.FindAll method.  This basically says that I want to find all categories in my datasource whose parentId matches the currentId I’m currently trying to populate with child nodes.  Every true match made adds the category object into the childCats variable.

Now that we have a collection of child objects that we need to create node object from, we begin an interation through each of these identified category objects.  We can now create a TreeNode object for the category, give it a tooltip if we want or whatever other properties we want to assign, but before we add it to the tree, or to its parent node, we are going to call the populateTree routine once again, but this time we will pass in the newly created TreeNode object.  By calling the routine recursively like this, we allow the application to provide a tree with unlimited node levels (should we actually want that, performance and usability will negate the use of unlimited node levels though, so add proper controls to that effect where necessary).

When the recursive call returns from the populateTree call, the tnAdd variable will or will not contain any child nodes.  We really don’t care, becuase we know we have at least one node to add to the tree, right?  Ensure we don’t have a null object, and if not, add the node to the childnodes collection of the original tree node.

Here’s an alternative version that populates the tree with folders under a defined starting folder.

private void loadTree()
{
    // Create a top-level node to start things off
    TreeNode tn = new TreeNode("Downloads", "0");

    // Pass the new node by reference, nodes will be added as children
    populateTree(Server.MapPath(@"~/secure/Downloads"), ref tn);

    // Add the nodes to the tree
    this.tvFolders.Nodes.Add(tn);
    this.tvFolders.DataBind();

}
private void populateTree(string startingPath, ref TreeNode tn)
{
    TreeNode tnAdd = null;

    // Obtain all subfolders
    DirectoryInfo di = new DirectoryInfo(startingPath);
    DirectoryInfo[] dirs = di.GetDirectories("*", SearchOption.TopDirectoryOnly);

    foreach (DirectoryInfo dis in dirs)
    {
        // Create a new node to add
        tnAdd = new TreeNode(dis.Name, dis.Name);

        // Check for children of the new node
        populateTree(dis.FullName, ref tnAdd);

        if (tnAdd != null)
            // Add the child to the node collection
            tn.ChildNodes.Add(tnAdd);
    }
}

The recursive routine is powerful, and this format makes it easy to adapt to various scenarios.  For instance, this folder recursion routine was simply copied from the above snippet and redone to work with a folder structure.  If I have the need at some point to include files in the tree, then I’ll update this post with it.  Or, if someone needs that, I’d be happy to work it up and provide it.


You might also enjoy these related posts

  1. Recursively populating a TreeView controls TreeNode collection – Updated As an update to my post on recursively populating a treeview with folders, I added code that will also provide files into TreeView control. Here is the full populateTree routine...
  2. Scripting a SQL 2000 Database from SQL 2005 I manage several databases (both SQL 2005 and SQL 2000) in my daily work routine and I finally decided to figure out something that has been troubling me every now...
  3. Sorting Generic.List Items Great example of sorting a Generic.List collection of objects can be found here. For future reference for myself, here is a class that can be reused in future projects whenever...
  4. A Simple Session State Item Manager for ASP.Net As I build applications there are times where I need to throw something into session state.  When I do so, I hate to have all the session state calls spread...
  5. Expose Yourself! Submit Your Web Site To Link Listings Link Directory LinkListings.net is a link directory site that you can submit your web site into to help your web site get more exposure. The link directory also allows you to submit...

About Wayne

Wayne John is a web developer in Southern California that shares his 25+ years of programming and web development experience freely and happily to anyone willing to learn. He also loathes speaking in the third person. If you enjoyed this post, make sure you subscribe to my RSS feed or get updates in your email.
This entry was posted in Web Development Tips and tagged , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

CommentLuv Enabled

Enter YourName @ YourKeywords in the Name field to take advantage of Keyword love. Please note, I normally won't approve comments that use products or niche keywords for a name. Get your comment approved, don't be a spammer.