2012-04-13 14 views
10

Mam kontrolę widoku drzewa w interfejsie formularza okna i ma kilka węzłów (z wieloma węzłami podrzędnymi). Chcę zapytać o kolekcję węzłów, aby, powiedzmy, 1. wybrać te, których nazwa zaczyna się od "x"
2. wybierz te, które nie mają żadnych danych w polu Węzeł.Tag.Zapytanie TreeNodeCollection

Czy ktoś może zaproponować mi sposób, aby to zrobić. Linq sprawi, że będzie to łatwe i zadbane, ale nie znalazłem nic na Linq do zapytania TreeNodeCollection.

Dzięki,

+1

Jaka jest głębokość twoich widoków drzewa? jeśli węzły podrzędne mają same węzły, potrzebujesz zapytania rekurencyjnego. –

+0

Na razie mogę powiedzieć, że głębokość to 1. – ViV

+1

Ten link może pomóc .... [1]: http://stackoverflow.com/questions/1815497/enumerating-collections-atat-are-not- inherently -ienienable/1815600 # 1815600 –

Odpowiedz

32

ponieważ TreeNodeCollection wstępne daty .NET 2.0, nie jest zbiorem rodzajowy, więc nie realizuje IEnumerable<T>, który jest „panem” typ dla LINQ dobroci.

Jednakże, można po prostu zadzwonić .Cast<TreeNode>() na TreeNodeCollection, a otrzymasz IEnumerable<TreeNode>, które może następnie zrobić wszystko, aby dobro LINQy.

(takie podejście działa dla każdej takiej kolekcji, która implementuje IEnumerable ale nie IEnumerable<T>)

+0

Dzięki. Wygląda na to, że to zrobi. Ale mam inny podstawowy problem. Próbowałem następujące: 'IEnumerable childNodes = treeView2.Nodes.Cast (); var x = childNodes.Where (node ​​=> node.Tag == null); ' To naprawdę nie działa, ponieważ childNodes tak naprawdę nie zawiera" ALL "węzłów potomnych. Zasadniczo próbuję to zrobić: Mam widok drzewa z n węzłów i każdym węzłem posiadającym węzły potomne. Chcę odfiltrować całe drzewo według pewnych kryteriów. Jak sobie z tym poradzić. Czy potrafisz zasugerować ... – ViV

+2

Jeśli chcesz przeszukać całe drzewo, metoda rekurencyjna wydaje się być naturalnym wyborem. Prawdopodobnie pojawiło się to wcześniej w SO - szybkie wyszukiwanie znalazło mnie [this] (http://stackoverflow.com/questions/177277/how-to-get-a-list-of-all-child-nodes-in- a-treeview-in-net), który znajduje się w VB.NET, ale powinien być łatwy do przetłumaczenia; będzie o wiele więcej. – AakashM

2

Próbowałem coś podobnego niedawno i walczył z podejściem LINQ dzięki kolekcji zagnieżdżonych węzłów pod każdym z rodziców.

Rozwiązałem mój problem za pomocą funkcji rekurencyjnej, która przeszukała wszystkie węzły. Dość elegancko.

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 
+0

Czy możesz podzielić się tym pomysłem. – ViV

3

Możesz spróbować coś takiego z operatorem Fixpoint pozwalając rekurencyjnych 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); 
} 

następnie

// 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>());