2008-10-07 7 views
14

Tôi có một điều khiển TreeView trong ứng dụng WinForms .NET của mình có nhiều cấp độ Childnode có Childnode với nhiều Childnode hơn, không có chiều sâu xác định. Khi người dùng chọn bất kỳ nút cha nào (không nhất thiết phải ở cấp cơ sở), làm thế nào tôi có thể nhận được danh sách tất cả các nút beneith mà nút cha?Cách lấy danh sách tất cả các nút con trong TreeView trong .NET

Ví dụ, tôi đang bắt đầu với điều này:

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 

Vấn đề là độ sâu vòng lặp này được định nghĩa và tôi chỉ bị nút chôn xuống ba cấp độ. Điều gì sẽ xảy ra nếu lần tiếp theo người dùng chọn một nút cha, có bảy cấp độ?

Trả lời

17

Sử dụng đệ quy

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

Chỉ cần chỉnh sửa nhanh: Dòng 3 nên gọi GetAllChildren –

+0

@ [Matt Hanson]: sửa dòng 3 theo nhận xét –

+2

Tôi khuyên bạn không nên gọi 'GetChildren' này vì nó không chỉ nhận trẻ em (tức là các nút trực tiếp hiện tại một) nó cũng được cháu, cháu tuyệt vời, và như vậy. Để rõ ràng, tôi tìm thấy nó tốt hơn để có 'GetDescendants' cho tất cả các hậu duệ và' GetChildren' cho chỉ là cấp độ ngay lập tức dưới đây. – Keith

12

bạn cần một hàm đệ quy để làm điều này [hoặc một vòng lặp tương đương, nhưng phiên bản đệ quy đơn giản] - giả:

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

đoạn mã này học tôi hàm đệ quy tốt hơn so với giáo viên của tôi ở đại học. – Shahin

12

Dưới đây là một đoạn mã mà tôi sử dụng để thực hiện tác vụ này từ thư viện cốt lõi của mình. Nó cho phép bạn liệt kê các nút hoặc là độ sâu đầu tiên hoặc hơi thở đầu tiên mà không sử dụng đệ quy, trong đó có chi phí xây dựng các khung xếp chồng trong công cụ JIT. Nó rất nhanh.

Để sử dụng nó chỉ đơn giản đi:

Danh sách < TreeNode> nút = TreeViewUtils.FlattenDepth (cây);

Xin lỗi bạn, bạn là người đứng đầu VB, tôi không thể đưa ra ví dụ, nhưng tôi chắc chắn bạn sẽ làm việc đó.

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

Tôi sẽ xem xét nó. Cảm ơn bạn đã chia sẻ, Adrian! –

+0

Cuối cùng là một cách tiếp cận không đệ quy. Cảm ơn rất nhiều. – ElektroStudios

1

Ik Dt de đang omgezet Naar vb.net gặp dit als 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

Tôi có một phương pháp mở rộng mà tôi sử dụng cho việc này:

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; 
     } 
} 

Đó là C#, nhưng có thể được tham chiếu từ VB hoặc chuyển đổi sang nó.

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

Thats nó

+0

BTW tvwOpt là gì? –

2

phương pháp Adrian của nó là tuyệt vời. Hoạt động khá nhanh và hoạt động tốt hơn phương pháp đệ quy. Tôi đã thực hiện một bản dịch sang VB. Tôi đã học được rất nhiều từ nó. Hy vọng rằng ai đó vẫn cần nó.

Để sử dụng một cách đơn giản:

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

Đây là mã, cheers! :

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

Nếu ai đó vẫn muốn làm phương pháp đệ quy, sử dụng mã Jop, và giữ TreeNodes (do đó bạn có thể sử dụng họ .tag, .name, .checked hoặc tài sản .text) đây là phiên bản của tôi

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

Thường nhận được giá trị tại nút được chỉ định là điều thú vị đối với người lập trình.Điều này có thể thu được như sau.Giả định rằng bạn có một điều khiển TextBox tên texbox1 và một điều khiển TreeView tên treeview1.Following sẽ trả về giá trị của văn bản tại các nút mức 0.

textbox1.Text = treeview1.nodes(0).Text.ToString()