我们正在使用WPF + MVVM + Visual Studio 2017。
我们想要添加实时过滤功能来进行转换:最初的回答
public ObservableCollection<RowViewModel> Rows { get; set; }
以下方法有两个关键优点:
- 它是为了与WPF运行时高效地配合工作,以最小化屏幕渲染而设计的,使用批量更新。
- 所以它很快。
- 由于下面列出了样板代码,相比您在网上找到的任何其他文档,更容易理解。
如果这对您有用,请告诉我,如果有任何问题,我会更新说明以使其更容易。
以下是步骤:
步骤1:不通知集合包装器
创建一个特殊的ObservableCollection,它不会触发更新事件。这是一次性的。我们想要自己触发批量更新事件,这样更快。
public class NonNotifyingObservableCollection<T> : ObservableCollection<T>
{
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { }
}
第二步:转换为非通知ObservableCollection
将其转换为使用这个新集合的私有变量。
private NonNotifyingObservableCollection<RowViewModel> rows
// ... and in constructor
rows = new NonNotifyingObservableCollection<RowViewModel>()
第三步:添加包装器
添加以下变量:
private ICollectionView rowsView;
public ICollectionViewLiveShaping RowsLiveView { get; set; }
在ViewModel构建完成后的Initialize()调用中(或者在构造函数中):
最初的回答:
dispatcher.InvokeAsync(() =>
{
this.rowsView = CollectionViewSource.GetDefaultView(this.rows);
this.rowsView.Filter = o =>
{
return ((RowViewModel)o).IsVisible == true;
};
this.RowsLiveView = (ICollectionViewLiveShaping)this.rowsView;
this.RowsLiveView.IsLiveFiltering = true;
this.RowsLiveView.LiveFilteringProperties.Add("IsVisible");
});
步骤四:添加项目
现在我们将项目添加到后备集合中,然后调用.Refresh()
来刷新视图:
this.rowsView.Add(new RowViewModel( ));
我们现在将网格绑定到
RowsLiveView
(而不是原始代码中的
Rows
)。
第五步:更新实时过滤
现在我们可以更新
IsVisible
属性,然后调用
.Refresh()
重新绘制网格。
rows[0].IsVisible=false
this.rowsView.Refresh()
更新
更新:这个答案可以简化。整个ICollectionViewLiveShaping
的重点是自动刷新,无需调用.Refresh()
。鉴于我们有一个NonNotifyingObservableCollection
并且我们正在手动控制一切与.Refresh()
,可以删除public ICollectionViewLiveShaping RowsLiveView { get; set; }
,直接使用RowsView
(将其作为属性{ get; set; }
,并使用普通的ObservableCollection<>
)。换句话说 - 对于少量行(例如<100),ICollectionViewLiveShaping非常好,但对于任何更多的行,从速度角度考虑,结合批量更新和手动Refresh()
的ICollectionView
更好。