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

2020-02-26 04:49发布

I have a TreeView control in my WinForms .NET application that has multiple levels of childnodes that have childnodes with more childnodes, with no defined depth. When a user selects any parent node (not necessarily at the root level), how can I get a list of all the nodes beneith that parent node?

For example, I started off with this:

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

The problem is that this loop depth is defined and I'm only getting nodes burried down three levels. What if next time the user selects a parent node, there are seven levels?

9条回答
孤傲高冷的网名
2楼-- · 2020-02-26 05:55

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.

查看更多
等我变得足够好
3楼-- · 2020-02-26 05:55

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
查看更多
甜甜的少女心
4楼-- · 2020-02-26 05:56

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;
    }
}
查看更多
登录 后发表回答