【问题标题】:How to filter a collection when binding it to ItemsSource?将集合绑定到 ItemsSource 时如何过滤集合?
【发布时间】:2013-04-11 04:25:18
【问题描述】:

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

有没有办法与 where property is ...进行绑定?

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

【问题讨论】:

  • 其实我是DHN。
  • 你能发布你的 ViewModel 或绑定到 TreeView 的类

标签: wpf mvvm count treeview


【解决方案1】:

没有办法直接过滤绑定中的集合。但是,WPF 允许使用 CollectionViewSource 过滤(以及排序和分组)集合。

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

<TreeView x:Name="Tree" ItemsSource="{Binding Items}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding ChildItems}">
            <HierarchicalDataTemplate.Resources>
                <CollectionViewSource x:Key="FilteredItems" 
                                        Source="{Binding ChildItems}"
                                        Filter="FilteredItems_OnFilter" />
            </HierarchicalDataTemplate.Resources>
            <TextBlock>
                <TextBlock.Text>
                    <MultiBinding StringFormat="{} {0} of {1} selected">
                        <Binding Path="Count" Source="{StaticResource FilteredItems}" />
                        <Binding Path="ItemsSource.Count" ElementName="Tree" />
                    </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

在代码隐藏中:

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

我尚未对其进行测试,但它应该可以正常工作。不过,你永远不会知道 WPF...

【讨论】:

【解决方案2】:

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

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

【讨论】:

  • -1 - 绝对避免使用代码隐藏。 - 来吧,这根本不是真的。如有必要,您可以使用后面的代码。想想CustomControl,如果没有后面的代码,你就无法实现。但是当代码背后是最简单的解决方案时,还有其他各种原因。如果你愿意尽量避免使用背后的代码。,我会和你在一起。
  • +1 for DHN,我认为自己是一个 MVVM 原教旨主义者,但这绝对不是真的。顺便说一句,行为只不过是代码隐藏......
  • 我区分了派生自 UserControl(又名视图)的控件和派生自 Control(又名自定义控件)的控件。当我谈到代码隐藏时,我只指前者。在视图的情况下,必须避免代码隐藏。如果它是基于代码隐藏的,你甚至如何测试这样的东西?如果您尝试实现的功能是纯视觉行为,则相当于在代码隐藏中实现它(我仍然认为没有必要,因为您可以在 XAML 中执行它或将其委托给行为),如果这是别的东西,你做错了
  • @GenaVerdel 严格,不必要且不正确。您是否曾尝试获取对话窗口的结果并将值传递给 VM?有一个简单的解决方案,带有事件回调或非常复杂的方法,涉及AttachedProperty 和正确的绑定。不知道你是不是真的想硬着头皮走。如果您只有一两个简单的对话框,请使用后面的代码。如果您有更复杂的应用程序,请使用AttachedProperty,因为这是值得的。
  • @DHN。实际上我使用的是 AttachedProperty 解决方案,因为这被证明是最好的方法。尽管如此,在对视图模型或其部分进行单元测试时,代码隐藏确实成为一个相当大的障碍。
猜你喜欢
  • 1970-01-01
  • 2010-12-10
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-08
  • 1970-01-01
  • 2023-03-07
相关资源
最近更新 更多