访问TreeView Control中的所有节点

我有一组带有节点和子节点的TreeView控件。 例如:

ROOT有A,B,C。

A具有a1,a2,a3,然后a1,a2也包含一些节点,如x1,x2,x3等。 像这样很多子节点都在那里。 我知道可以使用带有for循环的循环。

我只想使用一个或两个for循环访问TreeView控件中的所有节点。

是否有任何算法或有其他方法吗?

还有一个问题:是否可以使用任何库函数在对象或字符串中获取树节点的路径? 例如:

 string S = TreeView1.Nodes[i].Nodes[j].Nodes 

不要使用嵌套循环,但要使用递归解决方案,如:

 void ListNodes( TreeNode node ) { foreach( var subnode in node.Nodes ) { ListNodes( subnode ); } // Print out node } 

为您的根节点调用此函数。

有关其他问题:请检查FullPath属性。

您可以使用递归函数遍历整个树:

 private void Traverse(TreeNodeCollection nodes) { foreach (TreeNode node in nodes) { Console.WriteLine("{0} -> {1}", node.Name, node.FullPath); Traverse(node.Nodes); } } 

然后你可以使用以下方法调用:

 Traverse(treeView.Nodes); 

并且它将首先遍历整个树的深度(即,在移动到下一个兄弟之前尽可能深地下降)。 传入Nodes集合意味着此代码将处理具有多个根节点的树。

上面的示例代码将打印出节点的名称以及树中该节点的完整路径

我不是递归的最大粉丝,但似乎你必须使用它。 我看到了一个聪明的例子,在线混合递归与迭代器。

  private int GetLevels(TreeNodeCollection treeNodes) { int level = 0; foreach (TreeNode node in TreeTopDown(treeNodes)) { int i = node.Level; if (i > level) level = i; } return level; } //TopDown Iterator private IEnumerable TreeTopDown(TreeNodeCollection treeNodes) { foreach (TreeNode node in treeNodes) { yield return node; foreach (TreeNode subNode in TreeTopDown(node.Nodes)) yield return subNode; } } //BottomUp Iterator private IEnumerable TreeBottomUp(TreeNodeCollection treeNodes) { foreach (TreeNode node in treeNodes) { foreach (TreeNode subNode in TreeBottomUp(node.Nodes)) yield return subNode; yield return node; } } 

您可以创建一个返回List的扩展方法。

后代扩展方法

 using System.Linq; using System.Windows.Forms; using System.Collections.Generic; public static class Extensions { public static List Descendants(this TreeView tree) { var nodes = tree.Nodes.Cast(); return nodes.SelectMany(x => x.Descendants()).Concat(nodes).ToList(); } public static List Descendants(this TreeNode node) { var nodes = node.Nodes.Cast().ToList(); return nodes.SelectMany(x => Descendants(x)).Concat(nodes).ToList(); } } 

获取TreeView的所有节点

 var nodes = this.treeView1.Descendants(); 

获取节点的所有子节点

 var nodes = this.treeView1.Nodes[0].Descendants(); 

您还可以使用linq在节点之间进行搜索。

我知道这个线程已经很老了,我的方法并没有完全减少递归量,它可能会稍微慢些但它会让我的代码更清晰一些。

我使用IEnumarable<>的扩展方法来展平任何树(不仅仅是TreeView节点):

 public static IEnumerable Flatten( this IEnumerable rootNodes, Func> childrenFunction) { return rootNodes.SelectMany( child => new[] { child } .Concat((childrenFunction(child) ?? Enumerable.Empty()) .Flatten(childrenFunction))); } 

然后我使用此方法获取树的所有节点:

 IEnumerable allNodes = treeView1.Nodes.Cast() .Flatten(n => n.Nodes.Cast()); 

您可以像我在我的应用程序中所做的那样使用Queue:

 List nodes = new List(); Queue queue = new Queue(); // // first insert all the root nodes into the queue. // foreach(TreeNode root in tree.Nodes) { queue.Enqueue(root); } 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); } } } } 

以下代码用于遍历TreeView的节点并仅返回叶节点:

 private IEnumerable LeafNodes(TreeNode root) { Stack stack = new Stack(); stack.Push(root); while (stack.Count > 0) { TreeNode current = stack.Pop(); if (current.Nodes.Count == 0) { yield return current; } else { foreach (TreeNode child in current.Nodes) { stack.Push(child); } } } } 

我使用它来访问类似浏览器的TreeView中的文件名:

 private void LogFileNames() { //There may be more than one node at root level foreach (TreeNode rootNode in FileTreeView.Nodes) { //Print only filenames, not directories foreach (TreeNode leafNode in LeafNodes(rootNode)) { Logger.Info(leafNode.Text); } } }