﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Wayne John &#187; recursion</title>
	<atom:link href="http://www.waynejohn.com/tag/recursion/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.waynejohn.com</link>
	<description>Something is stirring, and I don&#039;t think it&#039;s a mouse...</description>
	<lastBuildDate>Thu, 22 Jul 2010 17:35:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Recursively populating a TreeView controls TreeNode collection</title>
		<link>http://www.waynejohn.com/recursively-populating-a-treeview-controls-treenode-collection/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=recursively-populating-a-treeview-controls-treenode-collection</link>
		<comments>http://www.waynejohn.com/recursively-populating-a-treeview-controls-treenode-collection/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 22:51:54 +0000</pubDate>
		<dc:creator>Wayne</dc:creator>
				<category><![CDATA[Web Development Tips]]></category>
		<category><![CDATA[controls]]></category>
		<category><![CDATA[generics]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[recursion]]></category>
		<category><![CDATA[treecontrol]]></category>

		<guid isPermaLink="false">/post/2008/01/30/Recursively-populating-a-TreeView-controls-TreeNode-collection.aspx</guid>
		<description><![CDATA[Every now and then you come across a scenario where a Treeview control is the best solution for presenting a hierarchical view of data.&#160; How do you populate the tree?&#160; A recursive routine is what you are looking for perhaps &#8230; <a href="http://www.waynejohn.com/recursively-populating-a-treeview-controls-treenode-collection/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Every now and then you come across a scenario where a Treeview control is the best solution for presenting a hierarchical view of data.&#160; How do you populate the tree?&#160; A recursive routine is what you are looking for perhaps (at least, I haven&#8217;t run into any other tree scenario where a recursive routine was not used).&#160; </p>
<p>A recursive routine is a routine that will call itself over and over, until the end of whatever </p>
<pre class="code"><span style="color: green">// Create a top-level node to start things off
</span>TreeNode tn = <span style="color: blue">new </span>TreeNode(<span style="color: #a31515">"Content Categories"</span>,<span style="color: #a31515">"0"</span>);
<span style="color: green">// Pass the new node by reference, nodes will be added as children
</span>populateTree(cats, <span style="color: blue">ref </span>tn);
<span style="color: green">// Add the nodes to the tree
</span><span style="color: blue">this</span>.tvCategories.Nodes.Add(tn);
<span style="color: blue">this</span>.tvCategories.DataBind();</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>We start off by creating a TreeNode object.&#160; 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<T> of custom category objects.&#160; Don&#8217;t be disturbed by the &#8216;cats&#8217;, they are just simple model objects, and we pass the new TreeNode object in as a reference object.</p>
<p>When the populateTree routine ends, our tn variable will contain all the children it found in the generic cats List<T> object.</p>
<pre class="code"><span style="color: blue">private void </span>populateTree(List<Category> categories, <span style="color: blue">ref </span>TreeNode tn)
{
    <span style="color: blue">int </span>currentId = <span style="color: blue">int</span>.Parse(tn.Value);
    TreeNode tnAdd = <span style="color: blue">null</span>;
    <span style="color: green">// Obtain all categories that are children to the parentId
    </span>List<Category> childCats = categories.FindAll(
    <span style="color: blue">delegate</span>(Category cat)
    {
        <span style="color: blue">return </span>cat.ParentId == currentId;
    });
    <span style="color: green">// Iterate through our subset of nodes that are children
    // of the provided tn node
    </span><span style="color: blue">foreach </span>(Category c <span style="color: blue">in </span>childCats)
    {
        <span style="color: green">// Create a new node to add
        </span>tnAdd = <span style="color: blue">new </span>TreeNode(c.Name, c.CategoryId.ToString());
        tnAdd.ToolTip = c.Description;
        <span style="color: green">// Check for children of the new node
        </span>populateTree(categories, <span style="color: blue">ref </span>tnAdd);
        <span style="color: blue">if </span>(tnAdd != <span style="color: blue">null</span>)
            <span style="color: green">// Add the child to the node collection
            </span>tn.ChildNodes.Add(tnAdd);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a></p>
<p>The populateTree routine begins by grabbing the current id value off the provided node.&#160; 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.&#160; The code continues by defining a null TreeNode object as well.</p>
<p>The first thing we are going to do is find any children within our data source.&#160; I chose to use an anonymous delegate to make that determination in conjunction with the Generic List<T>.FindAll method.&#160; This basically says that I want to find all categories in my datasource whose parentId matches the currentId I&#8217;m currently trying to populate with child nodes.&#160; Every true match made adds the category object into the childCats variable.</p>
<p>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.&#160; 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.&#160; 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).</p>
<p>When the recursive call returns from the populateTree call, the tnAdd variable will or will not contain any child nodes.&#160; We really don&#8217;t care, becuase we know we have at least one node to add to the tree, right?&#160; Ensure we don&#8217;t have a null object, and if not, add the node to the childnodes collection of the original tree node.</p>
<p><strong>Here&#8217;s an alternative</strong> version that populates the tree with folders under a defined starting folder.</p>
<pre class="code"><span style="color: blue">private void </span>loadTree()
{
    <span style="color: green">// Create a top-level node to start things off
    </span>TreeNode tn = <span style="color: blue">new </span>TreeNode(<span style="color: #a31515">"Downloads"</span>, <span style="color: #a31515">"0"</span>);

    <span style="color: green">// Pass the new node by reference, nodes will be added as children
    </span>populateTree(Server.MapPath(<span style="color: #a31515">@"~/secure/Downloads"</span>), <span style="color: blue">ref </span>tn);

    <span style="color: green">// Add the nodes to the tree
    </span><span style="color: blue">this</span>.tvFolders.Nodes.Add(tn);
    <span style="color: blue">this</span>.tvFolders.DataBind();

}
<span style="color: blue">private void </span>populateTree(<span style="color: blue">string </span>startingPath, <span style="color: blue">ref </span>TreeNode tn)
{
    TreeNode tnAdd = <span style="color: blue">null</span>;

    <span style="color: green">// Obtain all subfolders
    </span><span style="color: #2b91af">DirectoryInfo </span>di = <span style="color: blue">new </span><span style="color: #2b91af">DirectoryInfo</span>(startingPath);
    <span style="color: #2b91af">DirectoryInfo</span>[] dirs = di.GetDirectories(<span style="color: #a31515">"*"</span>, <span style="color: #2b91af">SearchOption</span>.TopDirectoryOnly);

    <span style="color: blue">foreach </span>(<span style="color: #2b91af">DirectoryInfo </span>dis <span style="color: blue">in </span>dirs)
    {
        <span style="color: green">// Create a new node to add
        </span>tnAdd = <span style="color: blue">new </span>TreeNode(dis.Name, dis.Name);

        <span style="color: green">// Check for children of the new node
        </span>populateTree(dis.FullName, <span style="color: blue">ref </span>tnAdd);

        <span style="color: blue">if </span>(tnAdd != <span style="color: blue">null</span>)
            <span style="color: green">// Add the child to the node collection
            </span>tn.ChildNodes.Add(tnAdd);
    }
}</pre>
<p><a href="http://11011.net/software/vspaste"></a><a href="http://11011.net/software/vspaste"></a></p>
<p>The recursive routine is powerful, and this format makes it easy to adapt to various scenarios.&#160; For instance, this folder recursion routine was simply copied from the above snippet and redone to work with a folder structure.&#160; If I have the need at some point to include files in the tree, then I&#8217;ll update this post with it.&#160; Or, if someone needs that, I&#8217;d be happy to work it up and provide it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.waynejohn.com/recursively-populating-a-treeview-controls-treenode-collection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
