2010-02-24 146 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