WPF应用程序框架(WAF)中的MVVM CollectionViews

时间:2010-01-13 12:06:24

标签: wpf mvvm collectionviewsource

简而言之,我的问题是:您如何更喜欢将过滤/排序/分组的ObservableCollections公开给WAF中的视图?

我对第一次尝试感到非常满意,该尝试涉及过滤VM并公开模型对象的ICollectionView以便View绑定到:

public StartDetailViewModel(IStartDetailView view, StartPoint start, Scenario scenario)
        : base(view)
    {
        this.scenario = scenario;
        this.start = start;

        this.startsViewSource = new CollectionViewSource();
        this.startsViewSource.Filter += new FilterEventHandler(Starts_Filter);
        this.startsViewSource.Source = scenario.Starts; 
    }
    public ICollectionView FilteredStarts
    {
        get
        {
            return startsViewSource.View;
        }
    }
    void Starts_Filter(object sender, FilterEventArgs e)
    {
        if (e.Item != null)
        {
            e.Accepted = (((StartPoint)e.Item).Date == this.start);
        }
    }
}

但是,直接暴露Model对象是不够的,因为每个项目现在都需要自己的ViewModel。

因此,CollectionViewSource.Source现在附加到一组视图。这个问题的主要问题是应用过滤器:

void Starts_Filter(object sender, FilterEventArgs e)
{
    //Since e.Item is now a view we are forced to ask the View for the ViewModel:
    StartItemViewModel vm = ((IStartItemView)e.Item).GetViewModel<StartItemViewModel>();
    [...]
}

这对我来说是错误的。有更好的方法吗?

更新

所以我恢复了Model对象的CollectionViewSource.Source,并维护了View绑定到的子View对象的单独集合。

当然,问题是为什么我在ViewModel中使用CollectionViewSource呢?

我认为以下原则适用:如果过滤/排序功能仅是View的属性(即备用视图可能合法地不提供此类功能),则应在View中使用CollectionViews(必要时使用代码隐藏) )。如果过滤/排序功能是模型的维度,则可以通过其他方式在ViewModel或Model中处理。

一旦你意识到MVVM视图中的代码隐藏是完全可以接受的,这是有道理的。

有任何意见吗?

1 个答案:

答案 0 :(得分:2)

我认为CollectionView的真正好处在于当您逐个浏览collectionview项目时需要报告信息。通过这种方式,您可以使用可能需要的CurrentPosition属性和MoveCurrentToNext(/ etc.)方法。我特别喜欢在添加/删除/更改集合中的项目属性更改/项目时能够在MVVM中报告PropertyChanged通知的想法。

我认为在需要更复杂通知的控件中使用它会更有意义(例如datagrid,您可能希望每次选择更改或添加新项目时都会引发PropertyChanged事件并保存到数据存储区控制)。

我希望这是有道理的。这就是我作为初学者所做的一切。

此外,除了datacontext以及您可能从视图模型中提供的共享数据外,我真的认为除了视图的代码隐藏之外什么都不应该。