C# 树在我添加到每个节点时会复制每个节点

本文关键字:节点 复制 添加 | 更新日期: 2023-09-27 17:55:44

所以基本上我正在做的是向后构建一棵树。我从叶子开始,然后添加它们的父母,然后是他们的(最后是一棵 3 级的树)。

添加叶子没有问题(我查询数据库,并为每个条目创建一个 TNode(TreeNode 类的扩展),然后将它们添加到树中)。此步骤中没有重复 - 当我去添加叶子的父母时,重复就会发生。

我遍历叶子树,当两片叶子有不同的节号(只是一个我想按数分组的数字)时,我几乎会创建一个新的父节点。

该程序正在做的是在每个父节点下创建每个叶节点的两组,因此它看起来像这样:

它不会让我发布图像,所以我会尝试用文本绘制树:像这样

    第 1 部分       儿童 1-1       儿童 1-2       儿童 1-3       儿童 1-1       儿童 1-2       儿童 1-3    第 2 部分       儿童 2-1       儿童 2-2             儿童 2-1       儿童 2-2 

这是正在执行此操作的代码...这真的很奇怪,因为当我调试它时,每个节点的子节点数量每次都按预期增长一个,但是一旦添加了所有父节点,每个叶子有两个......

我也尝试将倒计时削减为仅 1,它增加了一个父母,并且它有一个孩子,这是重复的......

无论如何,代码:

请注意,switch 语句并不重要,它们只是设置新节点的文本

private void addLvl1Nodes() {
    int i = 0;
    TNode newNode = null;
    int count = tv_master.Nodes.Count;
    while (i < count) {
        TNode tn = (TNode)tv_master.Nodes[i];//get current node
            //if i = 0, then newNode has not been set, so make a new one!
            if ((i == 0)||
                (tn.Section != ((TNode)tv_master.Nodes[i-1]).Section )||
                (tn.Text.Substring(0, 1) != tv_master.Nodes[i - 1].Text.Substring(0, 1))){
                newNode = new TNode("");
                tv_master.Nodes.Add(newNode);
                switch (tn.Text.Substring(0, 1)) {
                    case "1": newNode.Text = "Part One"; break;
                    case "2": newNode.Text = "Part Two"; break;
                    case "3": newNode.Text = "Part Three"; break;
                }
                newNode.Section = tn.Section;
            }
        newNode.Nodes.Add(tn);
        i++;
    }
}

希望有人以前遇到过类似的错误 - 因为我找不到解决方案。

多谢!

++++++++

+++++

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

对于遇到类似问题的任何人来说,这是我代码的最终副本,现在可以按预期工作:)

private void addLvl1Nodes() {
            TNode newNode = null;
            List<TNode> nodes = tv_master.Nodes.Cast<TNode>().ToList();
            tv_master.Nodes.Clear();
            for(int i = 0; i<nodes.Count; i++){
                TNode tn = nodes[i];
                if ((i == 0) ||
                    (tn.Section != nodes[i-1].Section) ||
                    (tn.Text[0] != nodes[i-1].Text[0])) {
                    newNode = new TNode("");
                    tv_master.Nodes.Add(newNode);
                    switch (tn.Text[0]) {
                        case '1': newNode.Text = "Part One"; break;
                        case '2': newNode.Text = "Part Two"; break;
                        case '3': newNode.Text = "Part Three"; break;
                    }
                    newNode.Section = tn.Section;
                }
                newNode.Nodes.Add(tn);
            }
        }

C# 树在我添加到每个节点时会复制每个节点

在进行此调用之前,您可能需要从其旧父级中删除 tn:

  newNode.Nodes.Add(tn);

否则,您实际上不会有两个单独的 tn(子节点)实例,但它会在层次结构中多次显示。 (一次直接在tv_master下,一次在新创建的节点下。

只保留两个单独的节点列表(或树)可能是有意义的。 一个用于保存新创建的父节点,另一个用于保存叶节点。 然后,您可以在最后将所有内容连接起来。 也许像这样开始你的循环:

List<TNode> listLeafNodes = new List<TNode>(tv_master.Nodes);
tv_master.Nodes.Clear();
for( int i=0; i<listLeafNodes.Count; ++i )
{
...
}

当然,我不确定你用的是什么类来做 TNode 和 tv_master。 我在MSDN上看到的TNode界面似乎没有任何.节点属性。 此外,似乎至少有 3 个不同的 TreeView 类。 TNode 的完全限定类名和tv_master的定义可能有助于我们更好地理解事物。

正如 ebyrob 已经解释的那样,您将相同的节点添加到树中两次,因此在开始时清除初始节点列表会有所帮助。

为了补充他们的答案,您的初始节点也被"移动"到根之外的原因是TreeNodeCollection.Add方法不仅将节点添加到其内部数组中,而且还更改节点的私有parent字段以指向其新的父节点。

这样,每个初始节点都会从树中的两个位置(根节点和第一个子节点)引用,但其 Parent 属性使两个引用都在其父节点下呈现。

这似乎不是一个真正的解决方案,但它仍然可以帮助您。通过分析我遇到的您提供的代码,您可以使用相同的节点集合来获取子元素以及附加新节点。但子元素永远不会从原始节点集合中删除。因此,基本上您拥有子节点以及同一集合中各节的新节点。

应从集合中删除已处理的子元素。但请注意,这样做时,while 循环中的表达式必须改变。

此外,您可以简化以下行

tn.Text.Substring(0, 1)

喜欢这个

tn.Text[0]

这也适用于代码示例中后面第一个字符的比较。