XAML 在WPF中,就MVVM而言,CollectionViewSource的正确用法是什么?

wz3gfoph  于 2023-06-19  发布在  其他
关注(0)|答案(1)|浏览(122)

CollectionViewSource类应该提供所谓的数据“视图”。这包括数据过滤、排序和分组。
现在,人们可能会认为,这是MVVM架构中视图的责任,但通常是用户决定他想要什么样的分组、排序或过滤。这些都是业务决策,属于ViewModel。此外,过滤是通过获取一个元素并决定它是否匹配filter来执行的,这肯定是视图模型的责任(然后可能传递给服务)。
看起来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模式,以便视图模型对其进行足够的控制呢?如果不应该,那么这个场景(集合分组、排序、过滤)在MVVM中实际上应该是什么样子?

vojdkbi0

vojdkbi01#

我这样使用CollectionViewSource

<ListBox ItemsSource="{Binding Source={StaticResource CollectionViewSourceResource}}" />

相关问题