递归树创建

Raf*_*aeu 5 c# recursion

Node在 C# 中有一个具有以下属性的类:

public class Node
{
   public int Id {get;set;}
   public int? ParentId {get;set;}
   public string Label {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

我有一个TreeView控件,它提供以下方法来创建新节点:

MyTreeView.CreateNode(key, label);
parent.Nodes.CreateNode(key, label);
Run Code Online (Sandbox Code Playgroud)

如果我想添加一个新的子节点,我需要使用第二种方法,否则使用第一种方法。两者都返回一个类型为 的对象TreeNode

考虑到根节点具有 ,您将如何在 C# 中创建一个递归函数来填充树视图ParentId = null

这是我到目前为止所做的:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

这是我的递归函数:

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

pes*_*ino 2

如果您的树视图控件派生自 System.Windows.Forms.TreeView 您可以替换

MyTreeView.CreateNode(key, label);
parent.Nodes.CreateNode(key, label);
Run Code Online (Sandbox Code Playgroud)

MyTreeView.Nodes.Add(key, label);
parent.Nodes.Add(key, label);
Run Code Online (Sandbox Code Playgroud)

因此,调用始终会转到 TreeNodeCollection 类型的 Nodes 集合。您现在可以使用 Nodes 集合作为参数,而不是 Node 对象。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样做有两个好处:

  1. 您不需要每次都查找父级。
  2. 您只有一个调用(TreeNodeCollection.Add)。

但是,如果您无法在每个根的 AddNode 调用中访问 TreeView.Nodes 集合,则必须在 AddNode 方法的顶部进行检查。

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;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)