Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive tree creation

Tags:

c#

recursion

I have a Node class in C# with the following properties:

public class Node
{
   public int Id {get;set;}
   public int? ParentId {get;set;}
   public string Label {get;set;}
}

I have a TreeView control which provides the following method to create a new node:

MyTreeView.CreateNode(key, label);
parent.Nodes.CreateNode(key, label);

If I want to add a new child node I need to use the second method otherwise the first one. Both returns an object of type TreeNode.

How would you create in C# a recursive function to populate the treeview considering that the root nodes have ParentId = null?

This is what I have done so far:

// create a list of root nodes
var roots = myList.Where(x => x.ParentId == null);
// send the roots to a recursive func
foreach(var root in roots)
{
   AddNode(null,root,myList);
}

this is my recursive function:

private void AddNode(Node parent, Node current, IList<Node> items)
{
   TreeNode treenode = null;
   if(parent == null)
   {
      treenode = mytree.CreateNode(current.Id.ToString(), current.Label);
   }else{
      var parentnode = mytree.GetNode(parent.Id.ToString());
      treenode = parentnode.Nodes.CreateNode(current.Id.ToString(), current.Label);
   }
   // call the recursion for the children
   var children = items.Where(x => x.ParentId == current.Id);
   foreach(var child in children)
   {
      AddNode(current, child, items);
   }
}
like image 835
Raffaeu Avatar asked Nov 13 '22 02:11

Raffaeu


1 Answers

If your tree view control is derived from System.Windows.Forms.TreeView you can replace

MyTreeView.CreateNode(key, label);
parent.Nodes.CreateNode(key, label);

with

MyTreeView.Nodes.Add(key, label);
parent.Nodes.Add(key, label);

So the call always goes to a Nodes collection which is of type TreeNodeCollection. Instead of your Node object you can now use the Nodes collection as parameter.

var roots = myList.Where(x => x.ParentId == null);
foreach (var root in roots)
{
    AddNode(mytree.Nodes, root, myList);
}

private void AddNode(TreeNodeCollection nodes, Node current, IList<Node> items)
{
    TreeNode treenode = nodes.Add(current.Id.ToString(), current.Label);

    var children = items.Where(x => x.ParentId == current.Id);
    foreach (var child in children)
    {
        AddNode(treenode.Nodes, child, items);
    }
}

This has two benefits:

  1. You don't need to lookup the parent each time.
  2. You only have one call (TreeNodeCollection.Add).

However, if you can not access the TreeView.Nodes collection in the AddNode call for each root you will have to check for that at the top of the AddNode method.

var roots = myList.Where(x => x.ParentId == null);
foreach (var root in roots)
{
    AddNode(null, root, myList);
}

private void AddNode(TreeNodeCollection nodes, Node current, IList<Node> items)
{
    if (nodes == null)
    {
        nodes = myTree.Nodes;
    }

    ...
}
like image 176
pescolino Avatar answered Dec 16 '22 09:12

pescolino