4

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

我对我的第一次尝试感到相当满意,其中涉及在 VM 上进行过滤并公开模型对象的 ICollectionView 以便视图绑定到:

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>();
    [...]
}

这对我来说感觉不对。有更好的方法吗?

更新

所以我恢复到模型对象的 CollectionViewSource.Source 并维护一个单独的视图绑定的子视图对象集合。

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

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

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

任何意见?

4

1 回答 1

2

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

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

我希望这是有道理的。这正是我作为初学者所总结的。

另外,我真的认为除了数据上下文和您可能从视图模型提供给它的共享数据之外,视图的代码隐藏中不应包含任何内容。

于 2013-02-23T02:14:44.743 回答