过滤器可观察集合 [英] filter an observable collection

查看:118
本文介绍了过滤器可观察集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个显示从观察到的集合项的的ListView 控制。这些项需要进行过滤。我能做到这一点与 Col​​lectionViewSource ,但过滤器需要每次更新项目的变化。

I have a ListView control that displays items from an observable collection. These items need to be filtered. I am able to do that with a CollectionViewSource, but the filter needs to be updated each time an item changes.

我的项目是这样的:

enum Status {Done, Failed, Skipped, ...}

class Project {
  public string Name {get;set;}
  public Status Status {get;set;}
  // etc. etc.
}

class ProjectViewModel : INotifyPropertyChanged {
  private Project project;

  public ProjectBuildInfoViewModel(ProjectBuildInfo project)
  {
    this.project = project;
  }

  public string Name
  {
     get { return project.Name; }
     set { project.Name = value; OnPropertyChanged("Name"); }
  }

  // etc. etc.
}

class CollectionViewModel {
  private ObservableCollection<ProjectViewModel> projects = 
             new ObservableCollection<ProjectViewModel>();

  public ObservableCollection<ProjectViewModel> Collection
  {
     get { return projects; }
     private set {projects = value; }
  } 
}

然后我有这个的ListView 的ItemSource 绑定到集合。

// member of the user control class
private CollectionViewModel collection = new CollectionViewModel();

// in the constructor
listView.ItemSource = collection.Collection.

这不会过滤任何东西。所以,我有这些复选框,并应注明哪些项目(根据国家)应该显示。我用那么 Col​​lectionViewSource

This doesn't filter anything. So I have these check boxes and they should indicate which items (depending of the state) should be displayed. I have used then a CollectionViewSource:

private void UpdateView()
{
  var source = CollectionViewSource.GetDefaultView(collection.Collection);
  source.Filter = p => Filter((ProjectViewModel)p);
  listStatus.ItemsSource = source;
}

该过滤器的方法是这样的:

The filter method looks like this:

private bool Filter(ProjectViewModel project)
{
     return (ckFilterDone.IsChecked.HasValue && ckFilterDone.IsChecked.Value && project.Status == Status.Done) ||
            (ckFilterFailed.IsChecked.HasValue && ckFilterFailed.IsChecked.Value && project.Status == Status.Failed) ||
            (ckFilterSkipped.IsChecked.HasValue && ckFilterSkipped.IsChecked.Value && project.Status == Status.Skipped);
}

这有它捕捉复选框的值的缺点,所以我必须调用这个方法(的UpdateView )每次复选框被选中的时间。但它的作品。

This has the disadvantage that it captures the values of the checkboxes, so I have to call this method (UpdateView) each time a checkbox is checked. But it works.

然而,该项目的状态不改变,如果完成未选中例如,当物品进入完成应该从视图中移除。显然,这不会改变,除非我再打电话的UpdateView 。所以,我需要调用这个方法,每次有新的变化。这看起来丑陋和低效给我。

However, the item state does change and if "done" is not checked for instance, when an item goes into "done" it should be removed from the view. Obviously that doesn't change unless I again call UpdateView. So I need to call this method each time something changes. That looks ugly and inefficient to me.

所以我的问题是,这能在一个更好的方式来完成?谢谢你。

So my question is, can this be done in a nicer way? Thank you.

推荐答案

绑定你的的ListView 通过创建一个属性直接过滤的集合,而不是的ObservableCollection -

Bind your ListView directly to the filtered collection instead of the ObservableCollection by creating a property -

public ICollectionView YourFilteredCollection
{
   get
   {      
      var source = CollectionViewSource.GetDefaultView(collection.Collection);
      source.Filter = p => Filter((ProjectViewModel)p);
      return source;
   }
}

所以,现在只是你需要在你的复选框在您的收藏调用刷新()状态更改事件这样的 -

So, now simply you need to call Refresh() on your collection on your check boxes state changed event like this -

YourFilteredCollection.Refresh();

要刷新基于项目类中的任何状态变化的集合,可以通过挂钩的项目类的的PropertyChanged 事件(这个类必须概括它实现INotifyPropertyChanged),并从那里你可以调用refresh这样的 -

To refresh the collection based on any state change in the item class, you can generalize it by hooking the PropertyChanged event of your item class (for this your class need to implement INotifyPropertyChanged) and from there you can call refresh like this -

foreach (YourClass item in collection.Collection)
{
  item.PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
}

void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
  YourFilteredCollection.Refresh();
}

所以,当你的项目类中的任何属性的更改,您的集合将被过滤掉。

So, whenever any property changes in your item class, your collection will be filtered.

这篇关于过滤器可观察集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆