首页 > 解决方案 > 如何为每个根节点子节点创建列表列表?

问题描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Dialog_System
{
    public partial class Form1 : Form
    {
        List<List<TreeNode>> allnodes = new List<List<TreeNode>>();

        public Form1()
        {
            InitializeComponent();

            for(int i = 0; i < advancedTreeView1.Nodes.Count; i++)
            {
                PrintNodesRecursive(advancedTreeView1.Nodes[i]);
            }
        }

        public List<TreeNode> PrintNodesRecursive(TreeNode oParentNode)
        {
            allnodes.Add(oParentNode);

            // Start recursion on all subnodes.
            foreach (TreeNode oSubNode in oParentNode.Nodes)
            {
                PrintNodesRecursive(oSubNode);
            }

            return allnodes;
        }
    }
}

如果 List allnodes 是这样的:

List<TreeNode> allnodes = new List<TreeNode>();

结果是:

节点

但我希望根节点 0 将成为它与他的孩子的列表。然后根节点 1 也成为它自己的子节点的列表。等等。因此,在 List allnodes 中,我将列出每个根节点及其子节点。

例如在根 Node0 下应该监听节点 3,4,5

标签: c#winforms

解决方案


AList<List<TreeNode>>对此不起作用,因为级别数是预先给出的,并且始终为 2。您必须创建一个可以接受值和子级列表的类

public class Node<T>
{
    public T Value { get; set; }
    public List<Node<T>> Children { get; } = new List<Node<T>>();
}

这定义了一个递归结构,因为每个都Node<T>包含一个List<Node<T>>. 它可以有一个固定值类型TreeNode;但是,通过使其通用化,我们使其可在其他情况下重用。

基本上,您想克隆TreeView. 我们可以这样克隆:

public Node<TreeNode> CloneRecursive(TreeNode treeNode)
{
    var node = new Node<TreeNode> { Value = treeNode };
    foreach (TreeNode subTreeNode in treeNode.Nodes) {
        node.Children.Add(CloneRecursive(subTreeNode));
    }
    return node;
}

我们面临的一个问题是,我们在 中没有根节点TreeView,因为它TreeView本身不是节点。因此,我使用了创建一个TreeNode代表整体的虚拟对象的技巧TreeView

var rootNode = new TreeNode("root", advancedTreeView1.Nodes.Cast<TreeNode>().ToArray());
Node<TreeNode> clone = CloneRecursive(rootNode);
List<Node<TreeNode>> allnodes = clone.Children;

或者,我们可以使用循环调整您的解决方案:

List<Node<TreeNode>> allnodes = new List<Node<TreeNode>>();
foreach (TreeNode treeNode in advancedTreeView1.Nodes) {
    allnodes.Add(CloneRecursive(treeNode));
}

另一种可能性是只存储节点文本(这是可能的,因为我们的节点类是通用的)。

public Node<string> CloneTextRecursive(TreeNode treeNode)
{
    var node = new Node<string> { Value = treeNode.Text };
    foreach (TreeNode subTreeNode in treeNode.Nodes) {
        node.Children.Add(CloneTextRecursive(subTreeNode));
    }
    return node;
}

推荐阅读