5

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

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

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

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

如果我想添加一个新的子节点,我需要使用第二种方法,否则使用第一种。两者都返回一个类型的对象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);
}

这是我的递归函数:

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

4 回答 4

2

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

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

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

所以调用总是转到 TreeNodeCollection 类型的节点集合。现在,您可以使用 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);
    }
}

这有两个好处:

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

    ...
}
于 2012-07-24T17:14:28.620 回答
0

试试这个代码:

var lookup = myList.ToLookup(n => n.ParentId.ToString());

Action<IEnumerable<TreeNode>> addChildren = null;
addChildren = tns =>
{
    var query =
        from tn in tns
        from cn in lookup[tn.Name]
        select tn.Nodes.CreateNode(cn.Id.ToString(), cn.Label);
    var nodes = query.ToArray();
    if (nodes.Length > 0)
    {
        addChildren(nodes);
    }
};

addChildren(
    lookup[null]
        .Select(n =>
            MyTreeView.CreateNode(n.Id.ToString(), n.Label)));

我无法完全测试它,因此您可能需要更改一些代码才能使其正常工作,但它应该相当接近。

于 2012-10-07T12:29:34.130 回答
0

我可能会做这样的事情......

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

    public Node(int? parentId, int id, string label)
    {
        ParentId = parentId;
        Id = id;
        Label = label;
    }
}

public class TreeNode : List<TreeNode>
{
    public string Key { get; set; }
    public string Label { get; set; }


    public IEnumerable<TreeNode> Descendants
    {
        get
        {
            yield return this;

            foreach (var child in this)
            {
                foreach (var descendant in child.Descendants)
                {
                    yield return descendant;
                }

            }
        }
    }

    public TreeNode(string key, string label)
    {
        Key = key;
        Label = label;
    }

    public void CreateNode(int id, string label)
    {
        Add(new TreeNode(id.ToString(), label));
    }
}

public class Tree
{
    private TreeNode _root = new TreeNode(null, null);

    public Tree(IEnumerable<Node> nodes)
    {
        nodes.ToList().ForEach(node => CreateNode(node.ParentId, node.Id, node.Label));
    }

    public void CreateNode(int? parentId, int id, string label)
    {
        if (parentId == null)
        {
            _root.CreateNode(id, label);
        }
        else
        {
            _root.Descendants.First(x => x.Key == parentId.ToString()).CreateNode(id, label);
        }
    }

    public IEnumerable<TreeNode> Descendants => _root.Descendants;
}
于 2015-10-23T05:06:33.310 回答
-1

试试这个代码:

Node{
     Id, Label, List<Tree> Children
}

Tree GetTree(id){
     var node=new Node();
     
     node.Id=id;
     node.Children=new List<Node>();
     
     List<Node> children = db.Nodes.Where(x => x.ParentId==id);
     
     foreach(child in children){
           var childTree=GetTree(child.Id);
           node.Children.Add(childTree);
     }
     
     return node;
}
于 2021-01-20T06:43:10.473 回答