我在 Windows 窗体 UI 上有一个树视图控件,它有几个节点(有多个子节点)。我想查询节点集合,例如 1. 选择名称以“x”开头的
那些 2. 选择那些在 Node.Tag 字段中没有任何数据的节点。
有人可以建议我一种方法来做到这一点。Linq 会让它变得简单而整洁,但我在 Linq 上没有发现太多查询 TreeNodeCollection 的内容。
谢谢,
因为TreeNodeCollection
早于 .NET 2.0,它不是通用集合,所以它没有实现IEnumerable<T>
LINQ 的“主”类型。
但是,您可以只调用.Cast<TreeNode>()
a TreeNodeCollection
,然后得到一个IEnumerable<TreeNode>
,然后您可以对它做所有 LINQy 的优点。
(这种方法适用于任何实现IEnumerable
但不是这样的集合IEnumerable<T>
)
您可以使用允许递归 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>());
我最近尝试了类似的方法,并且由于每个父节点下的嵌套节点集合而在 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