2008-10-07 96 views
14

我的WinForms .NET應用程序中有一個TreeView控件,該控件具有多個級別的childnodes,其中包含具有更多childnodes且沒有定義深度的childnodes。當用戶選擇任何父節點(不一定在根級別)時,如何獲得與父節點相關的所有節點的列表?如何在.NET中的TreeView中獲取所有子節點的列表

例如,我開始了與此:

Dim nodes As List(Of String) 

For Each childNodeLevel1 As TreeNode In parentNode.Nodes 
    For Each childNodeLevel2 As TreeNode In childNodeLevel1.Nodes 
     For Each childNodeLevel3 As TreeNode In childNodeLevel2.Nodes 
      nodes.Add(childNodeLevel3.Text) 
     Next 
    Next 
Next 

的問題是,這個循環深度定義,我纔剛剛節點安葬下來三個層次。如果下次用戶選擇父節點時,會有七個級別?

回答

17

使用遞歸

Function GetChildren(parentNode as TreeNode) as List(Of String) 
    Dim nodes as List(Of String) = New List(Of String) 
    GetAllChildren(parentNode, nodes) 
    return nodes 
End Function 

Sub GetAllChildren(parentNode as TreeNode, nodes as List(Of String)) 
    For Each childNode as TreeNode in parentNode.Nodes 
    nodes.Add(childNode.Text) 
    GetAllChildren(childNode, nodes) 
    Next 
End Sub 
+0

只是一個快速編輯:第3行應該調用GetAllChildren – 2008-10-07 18:49:46

+0

@ [Matt Hanson]:更正的第3行按照註釋 – 2008-10-08 02:36:17

+2

我建議不要調用這個`GetChildren`,因爲它不只是讓孩子(即節點直接在當前一)它也得到了孫子孫輩,等等。爲了清楚起見,我發現爲所有後代和`GetChildren`提供`GetDescendants`更好。 – Keith 2010-05-05 07:33:44

12

你需要一個遞歸函數來做到這一點[或循環相當,但遞歸版本是簡單的 - 僞代碼:

function outputNodes(Node root) 
    writeln(root.Text) 
    foreach(Node n in root.ChildNodes) 
     outputNodes(n) 
    end 
end 
+1

返回文本值這個代碼片斷了解到我的遞歸函數比我在大學裏的老師比較好。 – Shahin 2011-03-03 13:06:45

12

這裏是一個代碼段我用來從我的核心庫執行此任務。它允許您在不使用遞歸的情況下首先列出節點深度或先排出節點,這在JIT引擎中具有構建堆棧幀的開銷。它非常快。

要使用它,只需轉至:

名單<樹節點>節點= TreeViewUtils.FlattenDepth(樹);

對不起,你是VB的頭,我不能舉一個例子,但我相信你會解決它。

public class TreeViewUtils 
{ 
    /// <summary> 
    /// This static utiltiy method flattens all the nodes in a tree view using 
    /// a queue based breath first search rather than the overhead 
    /// of recursive method calls. 
    /// </summary> 
    /// <param name="tree"></param> 
    /// <returns></returns> 
    public static List<TreeNode> FlattenBreath(TreeView tree) { 
     List<TreeNode> nodes = new List<TreeNode>(); 

     Queue<TreeNode> queue = new Queue<TreeNode>(); 

     // 
     // Bang all the top nodes into the queue. 
     // 
     foreach(TreeNode top in tree.Nodes) { 
      queue.Enqueue(top); 
     } 

     while(queue.Count > 0) { 
      TreeNode node = queue.Dequeue(); 
      if(node != null) { 
       // 
       // Add the node to the list of nodes. 
       // 
       nodes.Add(node); 

       if(node.Nodes != null && node.Nodes.Count > 0) { 
        // 
        // Enqueue the child nodes. 
        // 
        foreach(TreeNode child in node.Nodes) { 
         queue.Enqueue(child); 
        } 
       } 
      } 
     } 

     return nodes; 
    } 

    /// <summary> 
    /// This static utiltiy method flattens all the nodes in a tree view using 
    /// a stack based depth first search rather than the overhead 
    /// of recursive method calls. 
    /// </summary> 
    /// <param name="tree"></param> 
    /// <returns></returns> 
    public static List<TreeNode> FlattenDepth(TreeView tree) { 
     List<TreeNode> nodes = new List<TreeNode>(); 

     Stack<TreeNode> stack = new Stack<TreeNode>(); 

     // 
     // Bang all the top nodes into the queue. 
     // 
     foreach(TreeNode top in tree.Nodes) { 
      stack.Push(top); 
     } 

     while(stack.Count > 0) { 
      TreeNode node = stack.Pop(); 
      if(node != null) { 

       // 
       // Add the node to the list of nodes. 
       // 
       nodes.Add(node); 

       if(node.Nodes != null && node.Nodes.Count > 0) { 
        // 
        // Enqueue the child nodes. 
        // 
        foreach(TreeNode child in node.Nodes) { 
         stack.Push(child); 
        } 
       } 
      } 
     } 

     return nodes; 
    } 

} 
1

益希代碼omgezet NAAR vb.net滿足DIT阿爾斯resultaat ... suc6

Public Function FlattenBreadth(ByVal tree As TreeView) As List(Of TreeNode) 
     Dim nodes As New List(Of TreeNode) 
     Dim queue As New Queue(Of TreeNode) 
     Dim top As TreeNode 
     Dim nod As TreeNode 
     For Each top In tree.Nodes 
      queue.Enqueue(top) 
     Next 
     While (queue.Count > 0) 
      top = queue.Dequeue 
      nodes.Add(top) 
      For Each nod In top.Nodes 
       queue.Enqueue(nod) 
      Next 
     End While 
     FlattenBreadth = nodes 
End Function 
12

我有我使用這個擴展方法:

public static IEnumerable<TreeNode> DescendantNodes(this TreeNode input) { 
    foreach (TreeNode node in input.Nodes) { 
     yield return node; 
     foreach (var subnode in node.DescendantNodes()) 
      yield return subnode; 
     } 
} 

這是C#,但可以從VB引用或轉換爲它。

0
nodParent As TreeNode 
'nodParent = your parent Node 
tvwOpt.Nodes.Find(nodParent.Name, True) 

完蛋了

2

阿德里安的方法,它的真棒。工作速度相當快,並且比遞歸方法效果更好。我已經完成了對VB的翻譯。我從中學到了很多東西。希望有人仍然需要它。

簡單地使用它:

Dim FlattenedNodes As List(Of TreeNode) = clTreeUtil.FlattenDepth(Me.TreeView1) 

下面是代碼,乾杯! :

Public Class clTreeUtil 
''' <summary> 
''' This static utiltiy method flattens all the nodes in a tree view using 
''' a queue based breath first search rather than the overhead 
''' of recursive method calls. 
''' </summary> 
''' <param name="tree"></param> 
''' <returns></returns> 
Public Shared Function FlattenBreath(Tree As TreeView) As List(Of TreeNode) 
    Dim nodes As List(Of TreeNode) = New List(Of TreeNode) 
    Dim queue As Queue(Of TreeNode) = New Queue(Of TreeNode) 

    '' 
    '' Bang all the top nodes into the queue. 
    '' 
    For Each top As TreeNode In Tree.Nodes 
     queue.Enqueue(top) 
    Next 

    While (queue.Count > 0) 
     Dim node As TreeNode = queue.Dequeue() 
     If node IsNot Nothing Then 
      '' 
      '' Add the node to the list of nodes. 
      '' 
      nodes.Add(node) 

      If node.Nodes IsNot Nothing And node.Nodes.Count > 0 Then 
       '' 
       '' Enqueue the child nodes. 
       '' 
       For Each child As TreeNode In node.Nodes 
        queue.Enqueue(child) 
       Next 
      End If 
     End If 
    End While 

    Return nodes 
End Function 

''' <summary> 
''' This static utiltiy method flattens all the nodes in a tree view using 
''' a stack based depth first search rather than the overhead 
''' of recursive method calls. 
''' </summary> 
''' <param name="tree"></param> 
''' <returns></returns> 
Public Shared Function FlattenDepth(tree As TreeView) As List(Of TreeNode) 
    Dim nodes As List(Of TreeNode) = New List(Of TreeNode) 

    Dim stack As Stack(Of TreeNode) = New Stack(Of TreeNode) 

    '' 
    '' Bang all the top nodes into the queue. 
    '' 
    For Each top As TreeNode In tree.Nodes 
     stack.Push(top) 
    Next 

    While (stack.Count > 0) 
     Dim node As TreeNode = stack.Pop() 

     If node IsNot Nothing Then 

      '' 
      '' Add the node to the list of nodes. 
      '' 
      nodes.Add(node) 

      If node.Nodes IsNot Nothing And node.Nodes.Count > 0 Then 
       '' 
       '' Enqueue the child nodes. 
       '' 
       For Each child As TreeNode In node.Nodes 
        stack.Push(child) 
       Next 
      End If 
     End If 

    End While 

    Return nodes 
End Function 

End Class 
0

如果有人仍然想要做遞歸方法,使用Jop的代碼,並保持樹節點(這樣你就可以使用他們的.TAG,.name和.checked或性質的.text)這裏是我的

版本
Public Shared Function GetChildren(objTree As TreeView) As List(Of TreeNode) 
    Dim nodes As List(Of TreeNode) = New List(Of TreeNode) 
    For Each parentNode As TreeNode In objTree.Nodes 
     nodes.Add(parentNode) 
     GetAllChildren(parentNode, nodes) 
    Next 

    Return nodes 
End Function 

Public Shared Sub GetAllChildren(parentNode As TreeNode, nodes As List(Of TreeNode)) 
    For Each childNode As TreeNode In parentNode.Nodes 
     nodes.Add(childNode) 
     GetAllChildren(childNode, nodes) 
    Next 
End Sub 
0

通常在指定的節點上得到一個值對程序員來說是很有趣的。這可以通過以下方式獲得。假設你有一個名爲texbox1 TextBox控件和一個名爲treeview1.Following TreeView控件將在節點級別0

textbox1.Text = treeview1.nodes(0).Text.ToString() 
相關問題