14

我在 Windows 窗体 UI 上有一个树视图控件,它有几个节点(有多个子节点)。我想查询节点集合,例如 1. 选择名称以“x”开头的
那些 2. 选择那些在 Node.Tag 字段中没有任何数据的节点。

有人可以建议我一种方法来做到这一点。Linq 会让它变得简单而整洁,但我在 Linq 上没有发现太多查询 TreeNodeCollection 的内容。

谢谢,

4

3 回答 3

42

因为TreeNodeCollection早于 .NET 2.0,它不是通用集合,所以它没有实现IEnumerable<T>LINQ 的“主”类型。

但是,您可以只调用.Cast<TreeNode>()a TreeNodeCollection,然后得到一个IEnumerable<TreeNode>,然后您可以对它做所有 LINQy 的优点。

(这种方法适用于任何实现IEnumerable但不是这样的集合IEnumerable<T>

于 2012-04-13T14:30:54.263 回答
3

您可以使用允许递归 lambda 的 Fixpoint 运算符尝试类似的操作

// 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>());
于 2012-04-13T14:43:43.977 回答
2

我最近尝试了类似的方法,并且由于每个父节点下的嵌套节点集合而在 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's children
            Dim soughtNode = FindNode(name, n)
            If soughtNode IsNot Nothing Then
                Return soughtNode
            End If
        End If
    Next

    Return Nothing

End Function
于 2012-04-13T11:47:04.460 回答