2010-02-24 97 views
2

首先我们有全能的代码!TreeNodeCollection参考问题

List nodes = new List(); 
TreeNode Temp = new TreeNode(); 

TreeNodeCollection nodeList = treeViewTab4DirectoryTree.Nodes; 

while (nodeList.Count != 0) 
{ 
    Temp = nodeList[0]; 

    while (Temp.FirstNode != null) 
    { 
     Temp = Temp.FirstNode; 
    } 

    if (!nodes.Contains(Temp.FullPath)) 
    { 
     nodes.Add(Temp.Text); 
    } 

    nodeList.Remove(Temp); 
}

现在的问题:我写了上面的代码,目的是创建一个包含树中所有节点的文本的列表。这是完美的。我遇到的问题是,当我从我的变量中删除节点时,它们也将从实际列表中删除。问题是如何制作节点列表的副本,以便我可以在不与ACTUAL列表混淆的情况下使用它们。如何在不参考它的情况下制作它的副本?任何帮助将不胜感激!

+0

FYI:在第二行,你不需要创建一个新的'TreeNode' - 你可以直接指定那个变量'null'来启动。 – 2010-02-24 13:50:50

+0

@Jon谢谢。我在我的代码中进行了更改 – Adkins 2010-02-24 15:07:21

+0

这是标准的WinForms TreeView吗?当然,你必须打算使用:列表 nodes = new List (); ? ...也没有必要初始化'Temp to anything:你可以使用:TreeNode Temp; – BillW 2010-02-24 15:08:41

回答

2

你的问题出现了,因为“nodeList”是对treeViewTab4DirectoryTree.Nodes的引用,而不是它的副本。你需要寻找一个.Copy(),.Clone(),这个解决方案完全取决于你正在使用什么类型的TreeNodeCollection(WinForms,ASP.net,别的东西?)。 ToArray()方法或类似取拷贝的集合的内容,而不是对现有集合的引用。

如果,例如,您正在使用asp.net和因此System.Web.UI.WebControls.TreeNodeCollection,你可以用一种方式.CopyTo方法与此类似:

TreeNode[] x = null; 
treeViewTab4DirectoryTree.Nodes.CopyTo(x, 0); 
+0

@ Rob我试过你的代码,但是编译器告诉我目标数组不能为null,也不能被取消赋值。有什么办法让它动态吗?如果CopyTo的签名专门调用Array,列表是否可以工作? – Adkins 2010-02-24 14:53:36

+1

@Adkins,那么你可能需要在使用它之前先初始化数组,具体的细节将归结为你正在使用的TreeNode类型。本质上,我的答案是你需要创建一个* new *集合来移除项目,而不是从nodeList或treeViewTab4DirectoryTree.Nodes中移除它们。 相反,您是否可以添加一个List ,您可以添加**想要保留的节点(或者您想要删除的节点),而不是试图修改现有的集合? – Rob 2010-02-24 15:03:23

+0

我不能在类型TreeNodeCollection和TreeNode元素集合(?huh?)之间隐式转换。然而,我可以通过TreeNodeCollection对每个TreeNode的集合进行foreach。感谢指针! – Adkins 2010-02-24 15:10:08

2

更新,以显示基于栈的方法:

List<String> result = new List<String>(); 
Stack<IEnumerator> nodeColls = new Stack<IEnumerator>(); 
IEnumerator nodes = treeViewTab4DirectoryTree.Nodes.GetEnumerator(); 

nodeColls.Push(null); 

while (nodes != null) 
{ 
    while (nodes.MoveNext()) 
    { 
     result.add(nodes.Current.FullPath); 
     if (nodes.Current.FirstNode != null) 
     { 
      nodeColls.Push(nodes); 
      nodes = nodes.Current.Nodes.GetEnumerator(); 
     } 
    } 

    nodes = nodeColls.Pop(); 
} 

下面的代码不起作用在评论所提到的,因为它不遍历整个树,但只需要第一叶节点每个顶级分支。

我实际上认为原始代码(在问题中)也是这样做的,因为我认为Remove在它下面找到第一个叶节点后实际上会删除顶层节点;但是它会尝试从顶级节点集合中删除叶节点,并且如果无法找到则忽略它。

原帖的,非功能代码

首先,你为什么需要从列表中删除的项目?

List<string> nodes = new List<string>(); 

foreach (TreeNode tn in treeViewTab4DirectoryTree.Nodes) 
{ 
    TreeNode temp = tn; 

    while (Temp.FirstNode != null) 
    { 
     Temp = Temp.FirstNode; 
    } 

    if (!nodes.Contains(Temp.FullPath)) 
    { 
     nodes.Add(Temp.Text); 
    } 
} 

要回答你的具体问题,假设节点集合实现IEnumerable,用途:

List<TreeNode> nodeList = new List<TreeNode>(treeViewTab4DirectoryTree.Nodes); 

如果你决定坚持使用while循环,你可以通过改变

保存instatiation
TreeNode Temp = new TreeNode(); 

TreeNode Temp = null; 

......你永远不会真正使用你创建的对象,至少在你显示的代码部分。

+0

@Arne我试着按照你说的创建一个列表,但收到一个错误,说构造函数得到了一个不正确的参数。我检查了它,它正在得到它想要的,但我无法摆脱错误信息。 – Adkins 2010-02-24 14:55:03

+0

@Arne也是你建议的循环只返回每个根节点的第一个孩子。这就是我去除元素的原因。当我完全打开其中一个时,我将其移除。当没有更多的删除,然后我完成了。 – Adkins 2010-02-24 15:06:54

+0

@Arne标准的WinForms TreeNodeCollection不是IEnumerable:讨论使IEnumerable兼容和示例代码迭代使用Linq签出:http://stackoverflow.com/questions/1815497/enumerating-collections-that-are-not-inherently -duumerable – BillW 2010-02-24 15:38:34