WindowsフォームUIにツリービューコントロールがあり、いくつかのノード(複数の子ノードを持つ)があります。たとえば、1.名前が「x」で始まるノードを選択するようにノードコレクションをクエリしたい
2. Node.Tagフィールドにデータがないノードを選択します。
誰かがこれを行う方法を教えてください。Linq は簡単できちんとしたものになりますが、Linq で TreeNodeCollection を照会するものはあまり見つかりませんでした。
ありがとう、
TreeNodeCollection
.NET 2.0 よりも古いため、ジェネリック コレクションではないためIEnumerable<T>
、LINQ の優れた「マスター」型である を実装していません。
ただし、 を呼び出すだけ.Cast<TreeNode>()
でTreeNodeCollection
を取得でき、それに対してすべての LINQy の利点IEnumerable<TreeNode>
を実行できます。
IEnumerable
(このアプローチは、実装するが実装しないそのようなコレクションに対して機能しますIEnumerable<T>
)
再帰ラムダを許可する 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