如何在TreeView控件中选择某个节点后获取其所有父节点(包括根节点)?

7
如果我有一个TreeView控件 (myTreeview),那么如何获取所选节点的所有父节点列表(包括直接父节点和祖先节点)呢?
4个回答

8

我建议您创建一组自己的树形辅助函数,例如,下面这个函数可以解决您的问题:

    public static class TreeHelpers
    {
        public static IEnumerable<TItem> GetAncestors<TItem>(TItem item, Func<TItem, TItem> getParentFunc)
        {
            if (getParentFunc == null)
            {
                throw new ArgumentNullException("getParentFunc");
            }
            if (ReferenceEquals(item, null)) yield break;
            for (TItem curItem = getParentFunc(item); !ReferenceEquals(curItem, null); curItem = getParentFunc(curItem))
            {
                yield return curItem;
            }
        }

        //TODO: Add other methods, for example for 'prefix' children recurence enumeration
    }

一个在您所在环境中使用的示例:

        IList<TreeNode> ancestorList = TreeHelpers.GetAncestors(node, x => x.Parent).ToList();

为什么使用这种方法比使用list<>.Add()更好?- 因为我们可以使用惰性LINQ函数,例如.FirstOrDefault(x => ...)

附注:要将“当前”项目包含在结果可枚举对象中,请使用TItem curItem = item,而不是TItem curItem = getParentFunc(item)


3

如果你需要实际对象,请递归使用TreeNode.Parent属性,直到到达根节点。像这样:

private void GetPathToRoot(TreeNode node, List<TreeNode> path)
{
    if(node == null) return; // previous node was the root.
    else
    {
        path.add(node);
        GetPathToRoot(node.Parent, path);
    }
}

谢谢!这非常有用。递归方法真的很递归;) - JotaPardo

1
亚历山大·马夫林斯基的回答非常有用,但我的方法有很多变化。我的代码不仅在方法上更短更清晰,而且在调用站点上也是如此(通过指定他的泛型)。
public static class TreeExtensions
{
    public static IEnumerable<TreeNode> GetAncestors(this TreeNode node)
    {
        if (node == null)
            yield break;
        while ((node = node.Parent) != null)
            yield return node;
    }
}

例如: var firstCheckedAncestor = treeNode.GetAncestors().First(x => x.Checked); 或者如果你真的需要每个父节点:var allAncestors = treeNode.GetAncestors().ToList();

但是,如果您计划让多个类使用相同的逻辑,则可以使用以下通用方法和每个类的几个扩展(以便在每个调用者上保留更简单的API):

public static IEnumerable<T> GetAncestors<T>(T item, Func<T, T> getParent)
{
    if (item == null)
        yield break;
    while ((item = getParent(item)) != null)
        yield return item;
}
public static IEnumerable<TreeNode> GetAncestors(this TreeNode node) => GetAncestors(node, x => x.Parent);
public static IEnumerable<Control> GetAncestors(this Control control) => GetAncestors(control, x => x.Parent);

-2

我认为你需要使用节点数组

List<TreeNode> resultNodes = new List<TreeNode>()
private void GetNodesToRoot(TreeNode node)
{
    if(node == null) return; // previous node was the root.
    else
    {
        resultNodes.add(node);
        GetNodesToRoot(node.Parent);
    }
}

1
嘿,不冒犯...我只是想说你不需要第二个参数。 - Saurabh Santhosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接