【问题标题】:Is ther any way to get access to a treeview node by giving number of node有没有办法通过给出节点数来访问树视图节点
【发布时间】:2016-01-20 11:59:23
【问题描述】:

我知道通过使用tagtext 可以搜索节点并找到它。

treeview1.Find(string name, bool searchAllChildren)

但在我的代码中,我有一个整数上的for 循环,它进行一些计算,然后我想将树视图的i-th 节点复制到一个新节点。例如,我想给i = 3,它应该给我node5 和所有孩子。

让我们在XML 中有一个类似下图的结构。我的目标是通过以下方式生成树视图。

首先复制所有节点和子节点直到nodeIV,然后复制节点node1, .... node7并保存在条件下,否则创建空节点。

-root
    -nodeI
    -nodeII
    -nodeIII
    -nodeIV
       -node1
          -children1
          -children2
          -children3
       -node2
       -node3
          -childrenA
          -childrenB
          -childrenC
       -node4
       -node5
       -node6
          -children
       -node7
          -childrenG
          -childrenR1
          -childrenR2
          -childrenR3
          -children

有没有这样的方法或者只有一个人可以通过这样做来访问节点,

【问题讨论】:

  • 你能展示和解释更多细节吗? int 和节点是什么关系?在一个简单的情况下,您可以使用treeView1.Nodes[i]
  • 这是 WinForms TreeView
  • @IvanStoev 是的。
  • @RenéVogt 请检查更新。

标签: c# .net winforms treeview


【解决方案1】:

首先,我不会重新发明轮子,而是从我对How to flatten tree via LINQ? 的回答中获取辅助函数,这对于任何类似树的结构都非常有用:

public static class TreeUtils
{
    public static IEnumerable<T> Expand<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> elementSelector)
    {
        var stack = new Stack<IEnumerator<T>>();
        var e = source.GetEnumerator();
        try
        {
            while (true)
            {
                while (e.MoveNext())
                {
                    var item = e.Current;
                    yield return item;
                    var elements = elementSelector(item);
                    if (elements == null) continue;
                    stack.Push(e);
                    e = elements.GetEnumerator();
                }
                if (stack.Count == 0) break;
                e.Dispose();
                e = stack.Pop();
            }
        }
        finally
        {
            e.Dispose();
            while (stack.Count != 0) stack.Pop().Dispose();
        }
    }
}

然后我会创建一对TreeView 特定助手:

public static class TreeViewUtils
{
    public static IEnumerable<TreeNode> AsEnumerable(this TreeNodeCollection source)
    {
        return source.Cast<TreeNode>();
    }

    public static IEnumerable<TreeNode> All(this TreeNodeCollection source)
    {
        return source.AsEnumerable().Expand(node => node.Nodes.Count > 0 ? node.Nodes.AsEnumerable() : null);
    }

    public static TreeNode Find(this TreeNodeCollection source, int index)
    {
        return source.All().Skip(index).FirstOrDefault();
    }
}

现在要获取树视图的i-th 节点,您可以简单地使用

var node = treeview1.Nodes.Find(i);

此外,您可以像这样获取任何节点的i-th 子节点

var childNode = node.Nodes.Find(i);

总之,我可以很容易地提供一个递归函数,只用更少的代码解决特定问题,但是这个小实用函数给你更多 - foreach 支持,子树 DFT 遍历的所有节点,LINQ 查询(例如按Tag 或其他条件搜索)等。

更新

现在的要求很奇怪,但这里是“原始”C# 函数(无 LINQ、无扩展方法、无迭代器方法)满足您的需求

public static class TreeViewUtils
{
    public static TreeNode FindNode(TreeNodeCollection nodes, int index)
    {
        int offset = -1;
        return FindNode(nodes, ref offset, index);
    }
    private static TreeNode FindNode(TreeNodeCollection nodes, ref int offset, int index)
    {
        for (int i = 0; i < nodes.Count; i++)
        {
            var node = nodes[i];
            if (++offset == index || (node = FindNode(node.Nodes, ref offset, index)) != null)
                return node;
        }
        return null;
    }
}

以及各自的用法

var node = TreeViewUtils.FindNode(treeview1.Nodes, i);

var childNode = TreeViewUtils.FindNode(node.Nodes, i);

【讨论】:

  • 非常感谢您的出色回答。有没有可能不使用LINQ,因为我不允许这样做!
  • 你是指System.Linq.Enumerable的函数?奇怪的。您是否允许编写和使用 extension 方法? 迭代器函数(比如我的Expand)?
  • 非常感谢!这就是我需要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-06
  • 2012-04-19
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
相关资源
最近更新 更多