Если у меня есть TreeView (myTreeview), как я могу получить список всех родительских узлов (родительских, родителей родителей и т. Д.) Выбранного узла?
Как получить все родительские (до корневых) узлы для выбранных в элементе управления TreeView?
Ответы (4)
Я бы порекомендовал вам создать набор ваших собственных помощников по дереву, например, следующий для вашей проблемы:
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 => ...)
P.S. чтобы включить «текущий» элемент в список результатов, используйте TItem curItem = item
вместо TItem curItem = getParentFunc(item)
Если вам нужны реальные объекты, используйте 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);
}
}
Ответ Александра Мавринского действительно полезен, но в моем подходе много изменений. Мой код короче и понятнее не только в методе, но и в сайтах вызовов (за счет указания его дженериков).
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);
Я думаю, вам нужно взять массив узлов
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);
}
}