14

以过滤为目的是如何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. 实时过滤如何工作?

更新:似乎将属性添加到集合的唯一方法ICollectionViewLiveShapingLiveFilteringProperties通过字符串。鉴于这种限制,是否甚至可以按另一个类(在这种情况下为工人的 EmployerID)中的属性进行过滤?

在这种情况下我试图做的甚至是一个可行的选择吗?

4

3 回答 3

14

您需要做的就是add a propertyLiveFilteringProperties您希望过滤器调用属性更改并为您的集合设置IsLiveFiltering为的位置。trueto enable live filtering

确保在属性更改PropertyChanged时引发事件,即您的类应该实现。EmployerIDWorkerINotifyPropertyChangedEvent

这将起作用 -

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;
}
于 2013-07-28T09:26:22.013 回答
2

我们正在使用 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) { /* Do nothing */ }
}

第 2 步:转换为 NonNotifyingObservableCollection

转换为使用这个新集合的私有变量。

private NonNotifyingObservableCollection<RowViewModel> rows;
// ... and in constructor
rows = new NonNotifyingObservableCollection<RowViewModel>();

第 3 步:添加包装器

添加这些变量:

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");
});

第 4 步:添加项目

现在我们将项目添加到支持集合中,然后调用.Refresh()以刷新视图:

this.rowsView.Add(new RowViewModel( /* Set properties here. */ ));

然后我们将网格绑定到RowsLiveView, (而不是Rows在原始代码中绑定到)。

第 5 步:更新实时过滤

现在我们可以更新IsVisible属性,然后调用.Refresh()重绘网格。

rows[0].IsVisible=false;
this.rowsView.Refresh(); // Hides the first row.

更新

更新:这个答案可以简化。的全部意义在于ICollectionViewLiveShaping无需调用即可自动刷新.Refresh()。鉴于我们有 aNonNotifyingObservableCollection并且我们正在使用 a 手动控制所有内容.Refresh(),因此可以删除public ICollectionViewLiveShaping RowsLiveView { get; set; }and,直接到RowsView(使用 , 使其成为属性{ get; set; }并使用 normal ObservableCollection<>。换句话说 - ICollectionViewLiveShaping 非常适合少量行(例如<100),但更重要的是,从速度的角度来看ICollectionView,结合批量更新和手册会更好。Refresh()

于 2019-06-14T08:26:37.897 回答
0

我对此进行了实验,看起来它不是为您(和我)想要的而设计的:更改过滤条件时自动过滤。当 DataGrid 的项目源的某些属性发生变化时,它会自动过滤,但不会在过滤条件发生变化时自动过滤 - 您必须手动调用 ICollectionViewSource.Refresh。

于 2017-02-20T07:59:03.380 回答