2013-01-16 86 views
0

我正在尋找一種方法來隱藏樹中的節點。 我過濾與節點類型的節點,這是我原來的結構:樹對象的隱藏節點遞歸

root 
+FolderA 
    -File1 
    -File2 
    -File3 
+FolderB 
    -File4 
    -File5 
    +FolderB-1 
      -File6 

這就是我想要做的事:

+root 
-File1 
-File2 
-File3 
-File4 
-File5 
-File6 

我已經創建了我的課XNode用類型和兒童的列表。 (這是縮寫僞語言)

Class XNode 
    MyType type; 
    string Name; 
    List<XNode> childrens; 
End Class 

我創建了一個工廠類,查詢我的數據庫,並建立原樹。

我創建了一個Xaml treeView UserControl來綁定我創建的根XNode。

通過Xaml不可能隱藏節點,此操作必須使用綁定對象(我的根Xnode創建)完成。

現在我的問題是: 有遞歸alghoritms取消「文件夾類型」節點,獲取其子節點,並將它們添加到父節點?

我嘗試:

public XNode RemoveFoldersElements(ref XNode rootNode) 
    { 

     if (rootNode != null) 
     { 
      if (rootNode.Children.Count > 0) 
      { 
       for (int i = 0; i < rootNode.Children.Count; i++) 
       { 
        XNode children = rootNode.Children.ElementAt(i); 
        if (children.WType == NodeType.Type_FOLDER) 
        { 
         XNode tempNode = RemoveFoldersElements(ref children); 
         if (tempNode != null) 
          rootNode.Children.Add(tempNode); 
         rootNode.Children.RemoveAt(i); 
        } 
        else 
        { 
         RemoveFoldersElements(ref children); 
        } 

       } 
      } 

     } 
     return null; 
    } 

但不是成功,因爲沒有Type_FOLDER的所有節點被刪除(它跳一級)! 任何想法?

+0

你可以遞歸每個節點,建立一個所有文件的列表,然後將它們作爲子節點添加到根結尾?如果你只關心訂單而不是層次結構,看起來你正在嘗試做太多的工作。 –

+0

這是一個懶惰模式。我想過濾這個有不同類型的項目的樹(不僅僅是文件) – davymartu

+0

你的例子使用了文件和文件夾,所以我在這種情況下做出了迴應。我不明白什麼是關於它的「懶惰模式」,在你遞歸的時候將你的過濾器應用到孩子身上,並且只用你想要的類型構建列表。 –

回答

0

OK,這裏的想法,壓平樹,同時過濾:

public static IEnumerable<TSource> Flatten<TSource>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TSource>> childCollectionSelector, Func<TSource, bool> predicate) 
{ 
    foreach (var item in source) 
    { 
     if(predicate(item)) 
      yield return item; 
     foreach (var subitem in childCollectionSelector(item).Flatten(childCollectionSelector, predicate).Where(predicate)) 
     { 
      yield return subitem; 
     } 
    } 
} 

,你可以使用它像這樣:

var rootList = new []{rootElement}; // Flattening works on the collection 
var files = rootList.Flatten(x => x.children, x => x.type == MyType.FILE); 

,它會工作,授予你沒有任何循環引用和所有集合都被初始化。如果你確實有循環依賴,你可以打個招呼StackOverflowException ...

+0

我試過你的解決方案,它的工作原理,但我必須隱藏不同類型的節點。根節點是一個沒有實現IEnumerable接口的對象... – davymartu

+0

@ user1696549然後像我在示例中那樣將它包裝在集合中,這可能是最簡單的方法。我不確定'隱藏不同類型的節點'是什麼意思,這是過濾掉的東西 - 你必須指定你的過濾器函數。 –