2013-01-16 85 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然后像我在示例中那样将它包装在集合中,这可能是最简单的方法。我不确定'隐藏不同类型的节点'是什么意思,这是过滤掉的东西 - 你必须指定你的过滤器函数。 –