How to get a list of all child nodes in a TreeView in .NET

时光怂恿深爱的人放手 提交于 2019-11-30 08:39:12
jop

Use recursion

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

you need a recursive function to do this [or a loop equivalent, but the recursive version is simpler] - pseudocode:

function outputNodes(Node root)
    writeln(root.Text)
    foreach(Node n in root.ChildNodes)
        outputNodes(n)
    end
end
Adrian Regan

Here is a snippet of code that I use to perform this task from my core library.
It allows you to list the nodes either depth first or breath first without the use of recursion, which has the overhead of constructing stackframes in the JIT engine. Its very fast.

To use it simply go:

List< TreeNode > nodes = TreeViewUtils.FlattenDepth(tree);

Sorry, you have a VB.Net tag; I can't give an example, but I'm sure you'll work it out.

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

I have an extension method that I use for this:

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

It's C#, but could be referenced from VB or converted to it.

Gusstavv Gil

Adrian's method it's awesome. Works quite fast and worked better than the recursion approach. I've done a translation to VB. I've learned a lot from it. Hopefully someone still needs it.

To use it simply:

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

Here is the code, 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

I have converted the code to VB.Net with this as a result:

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
Sunil
nodParent As TreeNode
'nodParent = your parent Node
tvwOpt.Nodes.Find(nodParent.Name, True)

Thats it

If someone still wants to do the recursion approach, using Jop's code, and keeping the TreeNodes (so you can use their .tag, .name, .checked or .text properties) here is my version

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

Usually get a value at the specified node is interesting to programmers.This can be obtained as follows.Assumes that you have a TextBox control named texbox1 and a TreeView control named treeview1.Following would return the value of text at nodes level 0.

textbox1.Text = treeview1.nodes(0).Text.ToString()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!