Запросить TreeNodeCollection

У меня есть элемент управления treeview на пользовательском интерфейсе формы Windows, и он имеет несколько узлов (с несколькими дочерними узлами). Я хочу запросить коллекцию узлов, чтобы, скажем, 1. выберите те, чье имя начинается с "x"
2. выберите те, у которых нет данных в поле Node.Tag.

Может кто-нибудь, пожалуйста, предложите мне способ сделать это. Linq сделает его простым и аккуратным, но я не нашел ничего особенного в Linq для запроса TreeNodeCollection.

Спасибо,

Ответ 1

Поскольку TreeNodeCollection pre-date.NET 2.0, это не общий набор, поэтому он не реализует IEnumerable<T>, который является "основным" типом для хорошего качества LINQ.

Однако вы можете просто вызвать .Cast<TreeNode>() на TreeNodeCollection, и вы получите IEnumerable<TreeNode>, после чего вы сможете сделать все LINKy добро.

(этот подход работает для любой такой коллекции, которая реализует IEnumerable, но не IEnumerable<T>)

Ответ 2

Вы можете попробовать что-то подобное с помощью оператора Fixpoint, разрешающего рекурсивные lambdas

// Fix point operator
public static Func<T, T> Fix<T>(Func<Func<T, T>, Func<T, T>> f)
{
    return t => f(Fix<T>(f))(t);
}

затем

// your treeView
var tv = new TreeView();

// Your filter Func
Func<TreeNode, bool> filterStartWithXorNoData =
    node => node.Text.StartsWith("x") || string.IsNullOrEmpty(node.Text);

// Your recursive lambda
var filteredNodes = Fix<IEnumerable<TreeNode>>(
    f =>
    nodeList =>
    nodeList.SelectMany(node => f(node.ChildNodes.Cast<TreeNode>()))
      .Union(nodeList.Where(filterStartWithXorNoData)))
      (tv.Nodes.Cast<TreeNode>());

Ответ 3

Я пробовал что-то подобное недавно и боролся с подходом LINQ из-за коллекции вложенных узлов под каждым родителем.

Я решил свою проблему с помощью рекурсивной функции, которая искала все узлы. Разумно элегантный.

VB:

Private Function FindNode(name As String, root As TreeNode) As TreeNode
    For Each n As TreeNode In root.Nodes
        If n.Name = name Then
            'Found, get out
            Return n

        Else
            'Recursively call FindNode to search this node children
            Dim soughtNode = FindNode(name, n)
            If soughtNode IsNot Nothing Then
                Return soughtNode
            End If
        End If
    Next

    Return Nothing

End Function