Wpf 将集合绑定到ItemsSource时如何筛选集合?

Wpf 将集合绑定到ItemsSource时如何筛选集合?,wpf,mvvm,count,treeview,Wpf,Mvvm,Count,Treeview,我创建了一个树视图,它对硬盘上的目录和文件进行建模。每个treeviewItem都有一个复选框,绑定到isSelected属性。我想要实现的是为每个父节点显示总文件数中选定文件的计数(10/12 10个文件,12个总选定文件) 有没有一种方法可以绑定属性为 <ContentPresenter Content="{Binding MyItems.Count where MyItems.IsSelected, Mode=OneTime}" Margin="2

我创建了一个树视图,它对硬盘上的目录和文件进行建模。每个treeviewItem都有一个复选框,绑定到isSelected属性。我想要实现的是为每个父节点显示总文件数中选定文件的计数(10/12 10个文件,12个总选定文件)

有没有一种方法可以绑定属性为

<ContentPresenter Content="{Binding MyItems.Count where MyItems.IsSelected, Mode=OneTime}"
                  Margin="2,0" />

无法直接筛选绑定中的集合。但是,WPF允许使用
CollectionViewSource
对集合进行筛选(以及排序和分组)

一种方法是在
itemstemplate
的资源中定义一个
CollectionViewSource
,它过滤
itemsource
并通过绑定到此
CollectionViewSource
的Count属性来获取通过过滤器的元素数。不过,您必须在codebehind中定义过滤器。看起来像这样:


在代码背后:

private void FilteredItems_OnFilter(object sender, FilterEventArgs e)
{
    var item = sender as Item;
    e.Accepted = item.IsSelected;
}

我还没有测试过它,但一般来说它应该可以工作。你永远不会知道WPF,不过…

我个人使用以下框架 这似乎满足了您的所有要求(使用LogoFX.Mini,因为它似乎足以满足您的需要)。 使用WrappingCollection.WithSelection作为项目资源 使用SelectionCount作为要显示的值。 如果您决定不使用框架,那么您应该通过专用行为订阅selection changed事件,创建专用依赖项属性,并在每次选择更改时更新它


最后一件事:一定要避免使用代码隐藏。它打破了整个MVVM原则。

事实上,我是DHN。你能发布你的ViewModels或绑定到TreeView-1的类吗?绝对不要使用代码隐藏。-拜托,那根本不是真的。如有必要,可以使用代码隐藏。想想
CustomControl
,如果没有代码隐藏,就无法实现一个。但是,当代码隐藏是最简单的解决方案时,还有其他各种原因。如果你愿意尝试避免使用代码,我会和你在一起。+ 1的DHN,我认为自己是一个相当的MVVM原教旨主义者,但这绝对不是真的。顺便说一句,行为只是代码隐藏。我区分了从UserControl(又名视图)派生的控件和从控件(又名自定义控件)派生的控件。当我谈到代码背后,我只提到前者。在视图的情况下,必须避免代码隐藏。如果这种东西是基于代码构建的,你怎么测试它呢?如果您试图实现的特性是纯视觉行为,那么它相当于在代码隐藏中实现它(我仍然认为没有必要,因为您可以在XAML中实现它,也可以将它委托给行为),如果它是其他东西,那么您就是在这样做wrong@GenaVerdel严格的,不必要的,不真实的。您是否尝试过获取对话框窗口的结果并将值传递给VM?有一个简单的解决方案,使用事件回调或非常复杂的方法,包括
AttachedProperty
和正确的绑定。我不知道你是否真的想走这条路。如果只有一个或两个简单的对话框,请使用隐藏的代码。如果您有一个更复杂的应用程序,请使用
AttachedProperty
,因为这是值得的。@DHN。实际上,我使用AttachedProperty解决方案,因为这被证明是最好的方法。然而,当涉及到对视图模型或其部分进行单元测试时,代码隐藏确实成为一个相当重要的障碍。什么?不需要对这个进行单元测试?那么如何检查此功能是否正常工作?自动化用户界面测试?包含当前选择是ViewModel的特权,而不是View的.Up-voting,因为这是WPF作者展示的方法-更新linky@Endrju-如何使用带void函数的return?!,正确的方法是设置e.Accepted=true;