我的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
问题在于定义了这个循环深度,并且我只将节点隐藏在三个级别。如果用户下次选择父节点时,有七个级别会怎么样?
答案 0 :(得分:18)
使用递归
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
答案 1 :(得分:13)
你需要一个递归函数来执行此操作[或等效的循环,但递归版本更简单] - 伪代码:
function outputNodes(Node root)
writeln(root.Text)
foreach(Node n in root.ChildNodes)
outputNodes(n)
end
end
答案 2 :(得分:13)
以下是我用来从核心库执行此任务的代码片段 它允许您在不使用递归的情况下首先列出深度优先或先呼吸的节点,这有在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;
}
}
答案 3 :(得分:12)
我有一个扩展方法,我用它:
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引用或转换为它。
答案 4 :(得分:3)
阿德里安的方法令人敬畏。工作速度非常快,比递归方法更好。我已经完成了对VB的翻译。我从中学到了很多东西。希望有人仍然需要它。
简单地使用它:
Dim FlattenedNodes As List(Of TreeNode) = clTreeUtil.FlattenDepth(Me.TreeView1)
这是代码,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
答案 5 :(得分:2)
我已将代码转换为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
答案 6 :(得分:1)
nodParent As TreeNode
'nodParent = your parent Node
tvwOpt.Nodes.Find(nodParent.Name, True)
多数民众赞成
答案 7 :(得分:1)
如果有人仍想进行递归方法,使用Jop的代码,并保留TreeNodes(这样你可以使用他们的.tag,.name,.checked或.text属性)这里是我的版本
ProductID = 401
答案 8 :(得分:1)
通常在指定节点获取一个值对程序员来说很有趣。这可以通过以下方式获得:假设您有一个名为texbox1的TextBox控件和一个名为treeview1的TreeView控件。以下将返回节点级别0的文本值
textbox1.Text = treeview1.nodes(0).Text.ToString()
答案 9 :(得分:0)
.Net WindowsForm TreeView中的
具有Find()
方法,带有可选标志'searchAllChildren'
。
在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;
}
}