简而言之,我的问题是:您更喜欢如何将过滤/排序/分组的 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 视图中的代码隐藏是完全可以接受的,这就是有道理的。
任何意见?