Wpf 绑定到ObservableCollection的筛选器树视图

Wpf 绑定到ObservableCollection的筛选器树视图,wpf,treeview,observablecollection,Wpf,Treeview,Observablecollection,我是WPF/可观察收藏的新手。 我们正在使用列表填充TreeView,列表是可观察的集合 我正在尝试筛选我的树,其中即使根节点/父节点不符合条件,并且子节点满足条件,我也无法筛选父节点 由于子节点满足条件,因此它应该与子节点的整个树路径一起显示 Root Animal Dog Cat Fish Fresh Water Salt Water 当你搜索“水”时,它应该显示Root——Fish Fresh water Salt water。到目前为止,

我是WPF/可观察收藏的新手。 我们正在使用列表填充TreeView,列表是可观察的集合

我正在尝试筛选我的树,其中即使根节点/父节点不符合条件,并且子节点满足条件,我也无法筛选父节点

由于子节点满足条件,因此它应该与子节点的整个树路径一起显示

Root
  Animal
     Dog
     Cat
  Fish
     Fresh Water
     Salt Water

当你搜索“水”时,它应该显示Root——Fish Fresh water Salt water。

到目前为止,我找到的最好的开箱即用的过滤和排序方法是CollectionView和CollectionViewSource duo

我在这里有一篇文章详细介绍了如何使用它们:

基本上,您要做的是在CollectionViewSource中托管集合,并在告诉ItemsControl(ListBox、ListView、TreeView)要在其中显示哪些项以及它们的显示顺序时,向Viewobject添加过滤器和排序定义。这样,您就不会更改集合,也不会跨多个集合操作单个项

例子 我的所有业务对象类都托管在ViewModels中。ViewModels都有一个名为MyRecord的属性,该属性属于该ViewModel的类类型(通过这种方式,无论我使用的是哪种ViewModelType,都可以调用该方法,很晚绑定!)

无论如何,正如我所记得的,我的筛选方法是这样的:

    private bool FilterByString(string filterString)
    {
        foreach (CustomerViewModel custVM in cvs.Source)
        {
            FilterChild(filterString, custVM);
            if (custVM.MatchesFilter(filterString))
            {
                return true;
            }
            else
            {
                return false;
            }

        }
    }

    private bool FilterChild(string filterString, Object parent)
    {
        bool match = false;
        if (parent.MyChildren != null && parent.MyChildren.Count > 0)
        {
            foreach (Object Child in parent.MyChildren)
            {
                //If any of the children return true, then this method returns true.
                //if all children return false, this method returns false.
                bool innerMatch = Child.MatchesFilter(filterString);
                match = (match == false ? innerMatch : match);
                Child.MatchesFilter(filterString);
                FilterChild(filterString, Child);
            }

        }
        bool outerMatch = parent.MatchesFilter;
        if (outerMatch || match)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
现在我想起来了。我实际上并不是在过滤孩子们,我只是把他们设置成崩溃。我将每个项上的展开属性设置为ViewModel上的一个属性,该属性是在调用MatchesFilter方法时设置的。仅筛选顶级项目(并且仅当其下的每个项目与筛选器不匹配时)


这可能不是您想要的功能,但目前正是我拥有的功能。

谢谢您的回答。但这似乎不适合我:(不确定它是否适用于分层数据。它在根级别应用筛选器,但在子级别节点不应用筛选器。我可能做错了什么。只是想与您确认,您是否已使用树状视图-分层数据对此进行了测试,如我在示例中所示。在上面的示例中,搜索仅适用于“动物”和“Fish”,它不适用于子元素。如果我键入“d”,它不会返回任何内容,因为“d”不在“Animal”或“Fish”中。我希望Animal-->Dog显示,因为Dog有“d”。请让我知道如何在树的所有级别应用筛选器。在筛选器逻辑方法中,您需要一些方法来检查子对象,以查看它们是否与筛选器匹配。我找不到希望为您发布的示例。在该示例中,我在层次结构中的每个类上都有一个实例方法,该方法使用字符串并返回bool对于匹配过滤器。然后在我的过滤器逻辑中,我有一个块,它沿着树一直走下去,获取项目并将值冒泡返回到顶层。(想想看,我还必须在扩展的classViewModels上有一个属性,我将其设置为=匹配过滤器…)感谢您的示例。我正在尝试使用TreeViewItem的Visibility属性实现过滤。我正在将其绑定到实体的属性,并根据过滤文本设置可见性。我看到的行为是,过滤后,它将不符合条件的节点显示为空节点节点旁边没有名称。似乎是其他人使用多个CollectionView使其工作。我没有尝试过此操作,但对您来说这可能是朝着正确方向迈出的一步: