我有一个显示可观测集合中项的 ListView
控件。这些项需要进行筛选。我可以使用 CollectionViewSource
进行筛选,但每次更改项时都需要更新筛选器。
我的项看起来像这样:
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.
这不会过滤任何内容。所以我有这些复选框,它们应该指示应显示哪些项目(取决于状态)。我已经使用 CollectionViewSource
:
private void UpdateView()
{
var source = CollectionViewSource.GetDefaultView(collection.Collection);
source.Filter = p => Filter((ProjectViewModel)p);
listStatus.ItemsSource = source;
}
filter 方法的语法如下:
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
)。不过它能够工作。
但是,项目状态确实会改变,如果例如 "done" 没有被选中,当一个项目进入 "done" 时,它应该从视图中删除。显然,除非我再次调用 UpdateView
,否则这不会改变。所以每次发生更改都需要调用此方法。这对我来说看起来很丑陋和低效。
因此,我的问题是,有没有更好的方法做到这一点?