为了过滤,有人可以帮我正确实施ICollectionViewLiveShaping
吗?关于这个问题,我没有在网上找到很多有用的文档。这就是我所拥有的:
public ICollectionView WorkersEmployed { get; set; }
WorkersEmployed = new CollectionViewSource { Source = GameContainer.Game.Workers }.View;
我没有使用GetDefaultView
,因为我需要在此集合上有多个过滤器实例。如果重要,GameContainer.Game.Workers
是ObservableCollection
。
ApplyFilter(WorkersEmployed);
private void ApplyFilter(ICollectionView collectionView)
{
collectionView.Filter = IsWorkerEmployed;
}
public bool IsWorkerEmployed(object item)
{
Worker w = item as Worker;
return w.EmployerID == this.ID;
}
这一切都有效,但当然必须手动刷新,这就是我尝试使用ICollectionViewLiveShaping
的原因。我能找到的最好的例子是this,但不幸的是我还是无法让它发挥作用。鉴于我在这里有什么,任何人都可以给我一个正确的方向,让实时过滤工作?
非常感谢任何帮助。
出于好奇,这真的是一项艰巨的任务吗?如果是这样,设计ICollectionViewLiveShaping
的人似乎做得很糟糕。
更新:似乎向ICollectionViewLiveShaping
的{{1}}集合添加属性的唯一方法是通过字符串。鉴于这种限制,是否可以按另一个类中的属性进行过滤(在本例中为Workers'EmployerID)?
任何对LiveFilteringProperties
有任何经验的人都可以告诉我,在这种情况下我想做什么甚至是一个可行的选择吗?老实说我不知道是不是因为缺乏文档和可用的例子。即使这是不可行的,也至少知道我是否在浪费时间。
答案 0 :(得分:11)
您需要做的只是add a property
LiveFilteringProperties
,您希望过滤器在属性更改时调用,并为集合IsLiveFiltering
设置true
to enable live filtering
}}
确保在PropertyChanged
属性发生变化时引发EmployerID
事件,即Worker
类应实现INotifyPropertyChangedEvent
。
这将起作用 -
public ICollectionViewLiveShaping WorkersEmployed { get; set; }
ICollectionView workersCV = new CollectionViewSource
{ Source = GameContainer.Game.Workers }.View;
ApplyFilter(workersCV);
WorkersEmployed = workersCV as ICollectionViewLiveShaping;
if (WorkersEmployed.CanChangeLiveFiltering)
{
WorkersEmployed.LiveFilteringProperties.Add("EmployerID");
WorkersEmployed.IsLiveFiltering = true;
}
答案 1 :(得分:1)
我们正在使用WPF + MVVM + Visual Studio 2017。
我们想将其转换为添加实时过滤:
public ObservableCollection<RowViewModel> Rows { get; set; }
以下方法具有两个主要优点:
如果有任何问题,请告诉我,是否适合您,我将更新说明以简化操作。
步骤:
创建一个不会触发更新事件的特殊ObservableCollection。这是一次性的。我们想自己触发更新批量更新事件,这更快。
public class NonNotifyingObservableCollection<T> : ObservableCollection<T>
{
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { /* Do nothing */ }
}
转换为使用此新集合的私有变量。
private NonNotifyingObservableCollection<RowViewModel> rows;
// ... and in constructor
rows = new NonNotifyingObservableCollection<RowViewModel>();
添加以下变量:
private ICollectionView rowsView;
public ICollectionViewLiveShaping RowsLiveView { get; set; }
并且在构造ViewModel之后(或者可能在构造函数中)在Initialise()调用中:
// Call on the dispatcher.
dispatcher.InvokeAsync(() =>
{
this.rowsView = CollectionViewSource.GetDefaultView(this.rows);
this.rowsView.Filter = o =>
{
// This condition must be true for the row to be visible on the grid.
return ((RowViewModel)o).IsVisible == true;
};
this.RowsLiveView = (ICollectionViewLiveShaping)this.rowsView;
this.RowsLiveView.IsLiveFiltering = true;
// For completeness. Changing these properties fires a change notification (although
// we bypass this and manually call a bulk update using Refresh() for speed).
this.RowsLiveView.LiveFilteringProperties.Add("IsVisible");
});
现在,我们将项目添加到支持集合中,然后调用.Refresh()
刷新视图:
this.rowsView.Add(new RowViewModel( /* Set properties here. */ ));
然后,将网格绑定到RowsLiveView
(而不是原始代码中绑定到Rows
)。
现在,我们可以更新IsVisible
属性,然后调用.Refresh()
重新绘制网格。
rows[0].IsVisible=false;
this.rowsView.Refresh(); // Hides the first row.
更新:此答案可以简化。 ICollectionViewLiveShaping
的全部要点是自动刷新,而无需调用.Refresh()
。假设我们有一个NonNotifyingObservableCollection
,并且我们正在使用.Refresh()
手动控制所有内容,则可以删除public ICollectionViewLiveShaping RowsLiveView { get; set; }
并直接删除到RowsView
(使用{{1}使其成为属性},并使用常规的{ get; set; }
。换句话说,ICollectionViewLiveShaping非常适合少量的行(例如<100),但是对于ObservableCollection<>
而言,它还可以与批量更新和手动{从速度的角度来看,{1}}更好。
答案 2 :(得分:0)
我对此进行了实验,看起来它不适合您(和我)想要的东西:更改过滤条件时自动过滤。它会在DataGrid项目源的某些属性发生更改时自动过滤,但在过滤条件发生变化时则不会自动过滤 - 您必须手动调用ICollectionViewSource.Refresh。