CollectionViewSource 违反了 MVVM 模式。

4

我有一个MVVM应用程序,我的几个VM中使用CollectionViewSource.GetDefaultView(datasource)初始化我的ICollectionView,并且它运行得非常完美。 我的担忧是,在我的VM中使用CVS时是否违反了MVVM?

谢谢大家的意见。


我正在处理的工作需要过滤和搜索,而我在虚拟机中的 CVS 的方式使得这对我来说更加容易和高效,除非有更简单、更高效的方法。 - asdbabil
违反MVVM模式有什么具体的问题?代码难写吗?难读吗?难测试吗?难改变吗?设计模式是指导,而不是法律。 - default.kramer
如果我有机会或方法让某事看起来或工作得更好,我不会犹豫去改变它。 - asdbabil
为什么不直接在视图模型中使用 LinQ 过滤集合呢? - Sheridan
3个回答

5

我通常喜欢在视图模型中公开一个集合,并在XAML中创建CollectionViewSource:

<Window.Resources>
    <CollectionViewSource x:Key="CollectionViewSource" Source="{Binding Items}">
        <i:Interaction.Behaviors>
            <behaviors:MyFilterLogic />
        </i:Interaction.Behaviors>
    </CollectionViewSource>
</Window.Resources>

<ItemsControl ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" />

还有行为类:

public class MyFilterLogic: Behavior<CollectionViewSource>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.Filter += AssociatedObjectOnFilter;
    }

    private void AssociatedObjectOnFilter(object sender, FilterEventArgs filterEventArgs)
    {
        // filter logic
    }
}

实际上,有些专家并不介意从视图模型中公开CollectionView: https://dev59.com/VHNA5IYBdhLWcg3wZ85R#979943


您不能使用此方法来使用过滤器。 - Gusdor
在我的情况下需要进行过滤和搜索。 - asdbabil
2
当然可以 - 你可以将自定义的行为逻辑附加到CollectionViewSource对象上。我已经修改了我的答案以显示过滤。 - eshaham
我把我的实现留在了虚拟机中。当我有时间时,我会回去使用您的方法改变一些东西。我想给你一个点赞,但我的 SOF 声望还不够高。谢谢 @eshaham - asdbabil
1
没关系,我很高兴能够帮助。 - eshaham
Erno de Weerd,在阅读了所有输入(包括您的输入)并进行了更多研究后,我得出结论:目前我可以将实现留在我的虚拟机中,但是我确实想回头将CVS放入XAMl中,并使用@eshaham的示例。这就是我将其标记为我的答案的原因。 - asdbabil

1

请看这个问题的答案:Trigger Filter on CollectionViewSource

它展示了一种使用MVVM方式通过在ViewModel中包装传统项来添加CollectionSourceView的方法。

据我所知,这种方式不违反MVVM,并且仍然可以使用漂亮的分组、过滤和排序功能。

不要因为你没有像大多数示例那样在Xaml中使用CollectionViewSources而感到难过;事实上,我觉得在ViewModel中使用它们比在代码中使用更好。

为了操作过滤、分组和排序,我向ViewModel添加命令,并在执行时更改ICollectionView。


这差不多就是我在虚拟机里面的情况。 - asdbabil
那又如何让你担心呢。就我所看,这并没有违反MVVM模式。 - Emond
它的事实是CVS位于System.Windows.Data命名空间中。 - asdbabil
@asdbabil 视图模型是专门为应用程序编写的。您不太可能在wpf、silverlight和/或windows phone 7中使用相同的视图模型。MVVM的理念是帮助您强制实现关注点分离。这不是一种帮助您设计可重用组件的模式。尽量不要因将视图模型程序集与WPF耦合而感到难过,相反,要担心将视图模型类与呈现它们的视图解耦。 - Gusdor
CVS在Data命名空间中的事实完全不相关。MVVM在其上面处于不同的抽象层。 - Emond

0

可能会让你感到不舒服的事情:

  • 那个工厂方法,GetDefaultView。由于其静态性质,它也让我感到很不舒服。
  • 正如你可能从在工作线程中更改 ObservableCollection<T> 所知道的那样,它绑定到 UI 线程。

CollectionViewSource 是一个抽象类,允许您指定如何组织集合,但它不显示集合 - ItemsControl 显示集合。这是良好的 MVVM!

通常,除非需要过滤器,否则我喜欢将 CollectionViewSource 保留在我的视图模型之外,因为它会使我的视图模型更加复杂。在长期运行中,DataTemplateSelectorVisualStateGroup 通常是更简单的更改集合呈现方式的方法。


1
我并不太关心在SL或Windows Phone 7应用程序中重复使用我的VM。更多的是,如果我们决定移动文件,比如说我们决定将所有VMs从WPF应用程序程序集中重新定位到类库程序集中。在VM中使用CVS感觉就像在VM中实例化控件,例如Combobox或Button。然而,在做了一些研究并得到一些反馈后,我感觉好多了 :) - asdbabil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接