首页 > 解决方案 > 就WPF中的MVVM而言,CollectionViewSource的正确用法是什么?

问题描述

CollectionViewSource类应该提供所谓的数据“视图”。这包括数据过滤、排序和分组。

现在,有人可能会认为,这是 MVVM 架构中视图的责任,但通常是用户决定他想要什么样的分组、排序或过滤。这些是业务决策,属于 viewmodel。此外,过滤是通过获取一个元素并决定它是否匹配过滤器来执行的,这绝对是 viewmodel 的责任(可能然后传递给服务)。

看来,这CollectionViewSource是直接从视图模型中公开的一个很好的候选者,因为后者可以完全控制其属性(例如GroupDescriptions)。但是,即使这个类驻留在 Windows.Data 命名空间中,它仍然在 PresentationFramework 程序集中,我从我的 BusinessLogic 程序集中引用它真的很不舒服,因为我几乎没有将它绑定到特定的 ( nomen omen ) 表示框架。

据我所见,CollectionViewSource 最常见的地方是控件(窗口)的资源,(令人惊讶的是)我可以从中绑定到视图模型。但是操作过滤、排序和分组是一团糟,因为您必须在视图和视图模型之间手动推送信息。仅举一个例子:

<CollectionViewSource x:Key="SuggestionItems" Source="{Binding Suggestions}">
  <CollectionViewSource.GroupDescriptions>
    <PropertyGroupDescription PropertyName="{Binding SuggestionGroupByProperty}"/>
  </CollectionViewSource.GroupDescriptions>
</CollectionViewSource>

这行不通,因为PropertyGroupDescription.PropertyName不是DependencyProperty. 所以我可能不得不设计我自己的 Xaml 扩展,以便能够将这些信息从视图模型绑定到视图。

我找不到任何关于如何ColletionViewSource适应 MVVM/WPF 框架的教程或文档。实际上,我的印象是,这并没有经过太多深思熟虑,因为例如,将资源放置CollectionViewSource在资源之外的任何地方都需要一些非常讨厌的恶作剧来简单地将收集推入内部。

例如(注意SelectedItem):

<DataGrid x:Name="grid" 
          AutoGenerateColumns="False" 
          ItemsSource="{Binding}" 
          SelectedItem="{Binding Path=DataContext.SelectedItem, RelativeSource={RelativeSource AncestorType={x:Type Window}}, Mode=TwoWay}">
  <DataGrid.DataContext>
    <CollectionViewSource x:Name="myViewSource" Source="{Binding MyCollection}" Filter="CollectionViewSource_OnFilter">
      <CollectionViewSource.GroupDescriptions>
        <PropertyGroupDescription PropertyName="Container" />
      </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
  </DataGrid.DataContext>
  <!-- (...) -->
</DataGrid>

那么CollectionViewSource应该如何规范地适应 MVVM 模式,以便 viewmodel 对其有足够的控制权呢?如果不应该,那么这个场景(集合分组、排序、过滤)在 MVVM 中应该如何实际看待?

标签: c#wpfxamlmvvmcollectionviewsource

解决方案


推荐阅读