Member 12969975 Ответов: 2

Перебрать все элементы дерева рекурсивных


Мне нужна функция, которая перебирает все TreeViewItems и дает клюву TreeViewItem, который получил определенный заголовок...

Например:

GetSearchedTreeViewItemByHeader(string _header)
{
  var searchedNode = new TreeViewItem();
  foreach(var node in treeView.Items)
  {
   if(node.Header == _header)
   {
    searchedNode = node
   }
  }

  return searchedNode
}


это работает только для первого элемента в treeView, кто-нибудь знает, как я делаю цикл все я понятия не имею, что слышал только от рекурсивного решения, но я не знаю, как это сделать...

заранее спасибо!


РЕДАКТИРОВАТЬ:
Я использую WPF

Что я уже пробовал:

TreeViewItems.Проверка элементов, для цикла, в то время как цикл

Richard Deeming

Вы ищете один соответствующий узел или все соответствующие узлы?

Member 12969975

один соответствующий узел

2 Ответов

Рейтинг:
2

Richard Deeming

Вот общий метод расширения для итерации всех узлов в любой Иерархии:

private static IEnumerable<T> SelectRecursiveIterator<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
{
    var stack = new Stack<IEnumerator<T>>();

    try
    {
        stack.Push(source.GetEnumerator());
        while (stack.Count != 0)
        {
            IEnumerator<T> iter = stack.Peek();
            if (iter.MoveNext())
            {
                T current = iter.Current;
                yield return current;

                IEnumerable<T> children = getChildren(current);
                if (children != null) stack.Push(children.GetEnumerator());
            }
            else
            {
                iter.Dispose();
                stack.Pop();
            }
        }
    }
    finally
    {
        while (stack.Count != 0)
        {
            stack.Pop().Dispose();
        }
    }
}

public static IEnumerable<T> SelectRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
{
    if (source == null) throw new ArgumentNullException(nameof(source));
    if (getChildren == null) return source;
    return SelectRecursiveIterator(source, getChildren);
}

Имея это на месте, вы можете перебирать все узлы в вашем дереве и возвращать либо все соответствующие узлы:
static IEnumerable<TreeNode> FindAllNodesByHeader(TreeView tree, string header)
{
    return tree.Items.Cast<TreeViewItem>().SelectRecursive(node => node.Items.Cast<TreeViewItem>()).Where(node => node.Header == header);
}

или только первый соответствующий узел:
static TreeNode FindFirstNodeByHeader(TreeView tree, string header)
{
    return tree.Items.Cast<TreeViewItem>().SelectRecursive(node => node.Items.Cast<TreeViewItem>()).FirstOrDefault(node => node.Header == header);
}


Member 12969975

у меня есть элемент управления WPF treeview, поэтому я получаю ошибку, что Itemscontrol не имеет определения для SelectRecursiv...

Richard Deeming

Вы должны были упомянуть, что используете WPF в своем вопросе!

Попробуй:

tree.Items.SelectRecursive(node => node.Items).FirstOrDefault(node => node.Header == header);

Member 12969975

я попробовал это сделать, но элемент управления WPF treeview не имеет метода selectrecursive

Richard Deeming

Похоже Items коллекция не реализуется IEnumerable<T>.

Попробуйте добавить .Cast<TreeViewItem>() в собственность:

tree.Items.Cast<TreeViewItem>().SelectRecursive(node => node.Items.Cast<TreeViewItem>()).FirstOrDefault(node => node.Header == header);

Member 12969975

статический TreeViewItem FindFirstNodeByHeader(дерево TreeView, строковый заголовок)
{
верните дерево.Предметы.Бросание&ЛТ;treeviewitem и GT;().SelectRecursive(узел =&ГТ; узел.Предметы.Бросание&ЛТ;treeviewitem и GT;()).Метода firstordefault(узел =&ГТ; узел.Заголовок = = заголовок);
}
я попробовал это сделать вот так и получил ошибку что TreeViewItem не имеет определения для SelectRecursive

Richard Deeming

Тогда вы не объявили метод расширения должным образом, или вам не хватает using заявление.

Member 12969975

у вас есть список использований?

Richard Deeming

Нет, потому что это зависит от пространства имен, в котором вы определили метод расширения, и от того, из какого пространства имен вы его вызываете.

Методы Расширения (Руководство По Программированию На C# )[^]

Рейтинг:
1

KarstenK

Рекурсия по этой задаче такова столь обычный что даже Microsoft опубликовала фрагмент кода recursice.

совет: если вы ищете определенный элемент, вы используете его в качестве дополнительного входного параметра.