如何获取 .NET 中 TreeView 中所有子节点的列表

发布于 07-07 08:14 字数 522 浏览 14 评论 0原文

我的 WinForms .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

问题是这个循环深度是定义的,我只将节点埋入三层。 如果下次用户选择父节点时,有七个级别怎么办?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

薔薇婲2024-07-14 08:14:24

使用递归

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

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
琴流音2024-07-14 08:14:24

您需要一个递归函数来执行此操作[或等效的循环,但递归版本更简单] - 伪代码:

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

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
终难遇2024-07-14 08:14:24

我有一个用于此目的的扩展方法:

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 引用或转换为它。

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.

一抹微笑2024-07-14 08:14:24

这是我用来从核心库执行此任务的代码片段。
它允许您以深度优先或呼吸优先的方式列出节点,而无需使用递归,而递归会产生在 JIT 引擎中构造堆栈帧的开销。 它的速度非常快。

要使用它,只需执行以下操作:

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

抱歉,您有一个 VB.Net 标签; 我无法举出例子,但我相信你会解决的。

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

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;
    }
}
旧情别恋2024-07-14 08:14:24
nodParent As TreeNode
'nodParent = your parent Node
tvwOpt.Nodes.Find(nodParent.Name, True)

就是这样

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

Thats it

岛徒2024-07-14 08:14:24

阿德里安的方法太棒了。 工作速度相当快并且比递归方法工作得更好。 我已经完成了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

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
疏忽2024-07-14 08:14:24

我已将代码转换为 VB.Net,结果如下:

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

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
花海2024-07-14 08:14:24

如果有人仍然想使用递归方法,使用 Jop 的代码,并保留 TreeNodes(这样你就可以使用它们的 .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

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
萌梦深2024-07-14 08:14:24

通常程序员对获取指定节点的值很感兴趣。这可以通过以下方式获取。假设您有一个名为 texbox1 的 TextBox 控件和一个名为 treeview1 的 TreeView 控件。以下将返回节点级别 0 处的文本值。

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

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()
简单爱2024-07-14 08:14:24

在 .Net WindowsForm TreeView 中,具有带有可选标志 'searchAllChildren'Find() 方法。

在 asp.net 中却没有。
为了获得相同的结果,我使用这个(类似于 Keith 答案,但在输入中我使用 TreeView)

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

in .Net WindowsForm TreeView has Find() method with the optional flag 'searchAllChildren'.

in asp.net instead there isn't.
to have the same result i use this (similar to Keith answer, but in input i use the TreeView)

public static IEnumerable<TreeNode> DescendantNodes2(this TreeView input)
{
    foreach (TreeNode node in input.Nodes)
    {
        yield return node;
        foreach (var subnode in node.DescendantNodes())
            yield return subnode;
    }
}
private static IEnumerable<TreeNode> DescendantNodes(this TreeNode input)
{
    foreach (TreeNode node in input.ChildNodes)
    {
        yield return node;
        foreach (var subnode in node.DescendantNodes())
            yield return subnode;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文