我的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
问题是这个循环深度是定义的,我只是将节点隐藏在三个级别.如果用户下次选择父节点时有七个级别怎么办?
使用递归
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
你需要一个递归函数来做这个[或一个循环等价,但递归版本更简单] - 伪代码:
function outputNodes(Node root) writeln(root.Text) foreach(Node n in root.ChildNodes) outputNodes(n) end end
这是我用来从我的核心库执行此任务的代码片段.
它允许您在不使用递归的情况下首先列出深度优先或先呼吸的节点,这具有在JIT引擎中构建堆栈帧的开销.它非常快.
要使用它,只需:
List< TreeNode > nodes = TreeViewUtils.FlattenDepth(tree);
对不起,你有一个VB.Net标签; 我不能举个例子,但我相信你会解决它.
public class TreeViewUtils
{
///
/// 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.
///
///
///
public static List FlattenBreath(TreeView tree) {
List nodes = new List();
Queue queue = new Queue();
//
// 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;
}
///
/// 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.
///
///
///
public static List FlattenDepth(TreeView tree) {
List nodes = new List();
Stack stack = new Stack();
//
// 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;
}
}
我有一个扩展方法,我用它:
public static IEnumerableDescendantNodes( this TreeNode input ) { foreach ( TreeNode node in input.Nodes ) { yield return node; foreach ( var subnode in node.DescendantNodes() ) yield return subnode; } }
它是C#,但可以从VB引用或转换为它.