我有一组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
答案 0 :(得分:9)
不要使用嵌套循环,而是使用递归解决方案,如:
void ListNodes( TreeNode node )
{
foreach( var subnode in node.Nodes )
{
ListNodes( subnode );
}
// Print out node
}
为您的根节点调用此函数。
有关您的其他问题:请查看FullPath
媒体资源。
答案 1 :(得分:6)
您可以使用递归函数遍历整个树:
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
集合意味着此代码将处理具有多个根节点的树。
上面的示例代码将打印出树中该节点的名称以及该节点的完整路径。
答案 2 :(得分:5)
我不是递归的最大粉丝,但似乎你必须使用它。我看到一个聪明的例子在线混合递归和迭代器。
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<TreeNode> 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<TreeNode> TreeBottomUp(TreeNodeCollection treeNodes)
{
foreach (TreeNode node in treeNodes)
{
foreach (TreeNode subNode in TreeBottomUp(node.Nodes)) yield return subNode;
yield return node;
}
}
答案 3 :(得分:3)
您可以创建一个返回List<TreeNode>
。
后代扩展方法
using System.Linq;
using System.Windows.Forms;
using System.Collections.Generic;
public static class Extensions
{
public static List<TreeNode> Descendants(this TreeView tree)
{
var nodes = tree.Nodes.Cast<TreeNode>();
return nodes.SelectMany(x => x.Descendants()).Concat(nodes).ToList();
}
public static List<TreeNode> Descendants(this TreeNode node)
{
var nodes = node.Nodes.Cast<TreeNode>().ToList();
return nodes.SelectMany(x => Descendants(x)).Concat(nodes).ToList();
}
}
获取TreeView的所有节点
var nodes = this.treeView1.Descendants();
获取节点的所有子节点
var nodes = this.treeView1.Nodes[0].Descendants();
您还可以使用linq在节点之间进行搜索。
祖先推广方法
要获得节点的祖先,您可能也对Ancestors extension methods感兴趣。
答案 4 :(得分:2)
我知道这个线程已经很老了,而且我的方法并没有完全减少递归量和它可能会稍微慢些但它会使我的代码更清晰。
我使用IEnumarable<>
的扩展方法来展平任何树(不仅仅是TreeView节点):
public static IEnumerable<T> Flatten<T>(
this IEnumerable<T> rootNodes,
Func<T, IEnumerable<T>> childrenFunction)
{
return rootNodes.SelectMany(
child => new[] { child }
.Concat((childrenFunction(child) ?? Enumerable.Empty<T>())
.Flatten(childrenFunction)));
}
然后我使用此方法获取树的所有节点:
IEnumerable<TreeNode> allNodes = treeView1.Nodes.Cast<TreeNode>()
.Flatten<TreeNode>(n => n.Nodes.Cast<TreeNode>());
答案 5 :(得分:1)
您可以像我在我的应用程序中所做的那样使用Queue:
List<TreeNode> nodes = new List<TreeNode>();
Queue<TreeNode> queue = new Queue<TreeNode>();
//
// 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);
}
}
}
}
答案 6 :(得分:0)
以下代码用于遍历TreeView的节点并仅返回叶节点:
let BtnVar = UIButton(title: "TrlTxt",
style: UIBarButtonItemStyle.Plain,
target: self,
action: #selector(self.NavRitBtnKlk(_:, Nam2Var)))
func NavLitBtnKlk(sender: UIButton, Nam1PsgVar: AnyObject)
{
/* CodTdo */
print("Clicked")
}
我用它来访问类似浏览器的TreeView中的文件名:
private IEnumerable<TreeNode> LeafNodes(TreeNode root)
{
Stack<TreeNode> stack = new Stack<TreeNode>();
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);
}
}
}
}