当我添加它时,C#树正在复制每个节点

时间:2011-05-06 16:21:41

标签: c# treeview tree duplicates

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

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

我循环遍历树叶,并且当两个叶子具有不同的分区编号时,几乎会创建一个新的父节点(只是我要分组的数字)。

程序正在做的是在每个父节点下创建每个叶节点的两个SET,所以它看起来像这样:

它不会让我发布图片,所以我会尝试用文字绘制树这样的东西

    Part 1
       child 1-1
       child 1-2
       child 1-3
       child 1-1
       child 1-2
       child 1-3
    Part 2
       child 2-1
       child 2-2       
       child 2-1
       child 2-2  

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

我也尝试过将数量减少到只有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);

            }
        }

3 个答案:

答案 0 :(得分:5)

在进行此调用之前,您可能需要从其旧父级中删除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接口似乎没有任何.Nodes属性。此外,似乎至少有3个不同的TreeView类。 TNode的完全限定类名和tv_master的定义可能有助于我们更好地理解事物。

答案 1 :(得分:2)

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

为了补充他们的答案,你的初始节点也被“移动”到根之外的原因是TreeNodeCollection.Add方法不仅将节点添加到其内部数组,而且还改变节点的私有{{} 1}}字段指向其新父级。

这样,每个初始节点都会从树中的两个地方引用(根节点和第一个子节点),但是它的parent属性会使两个引用都在其父节点下呈现

答案 2 :(得分:1)

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

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

此外,您可以简化以下行

tn.Text.Substring(0, 1)
像这样

tn.Text[0]

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