如何在 .NET 中的 TreeView 中获取所有子节点的列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/177277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get a list of all child nodes in a TreeView in .NET
提问by Matt Hanson
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?
我的 WinForms .NET 应用程序中有一个 TreeView 控件,它具有多个级别的子节点,这些子节点具有更多子节点,但没有定义的深度。当用户选择任何父节点(不一定在根级别)时,如何获取该父节点下所有节点的列表?
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?
问题是这个循环深度是定义的,我只让节点埋在三个层次上。如果下次用户选择父节点时,有七个级别怎么办?
回答by 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
回答by Steven A. Lowe
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
回答by 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.
这是我用来从我的核心库执行此任务的一段代码。
它允许您在不使用递归的情况下列出深度优先或呼吸优先的节点,递归具有在 JIT 引擎中构建堆栈帧的开销。它的速度非常快。
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.
抱歉,您有一个 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;
}
}
回答by Keith
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.
它是 C#,但可以从 VB 引用或转换为它。
回答by 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.
阿德里安的方法太棒了。工作速度非常快,并且比递归方法工作得更好。我已经翻译成VB了。我从中学到了很多。希望有人仍然需要它。
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
回答by Gusstavv Gil
I have converted the code to VB.Netwith this as a result:
因此,我已将代码转换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
回答by Gusstavv Gil
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
如果有人仍然想做递归方法,使用 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
回答by antony thomas
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.
通常获取指定节点的值对程序员来说很有趣。这可以通过以下方式获得。假设您有一个名为 texbox1 的 TextBox 控件和一个名为 treeview1 的 TreeView 控件。以下将返回节点级别 0 的文本值。
textbox1.Text = treeview1.nodes(0).Text.ToString()
回答by Sunil
nodParent As TreeNode
'nodParent = your parent Node
tvwOpt.Nodes.Find(nodParent.Name, True)
Thats it
就是这样

