Tengo un control ListView
que muestra elementos de una colección observable. Estos artículos necesitan ser filtrados. Puedo hacer eso con un CollectionViewSource
, pero el filtro debe actualizarse cada vez que cambia un elemento.Filtrar una colección observable
Mis artículos se parece a esto:
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; }
}
}
entonces tengo este ListView
cuya ItemSource
se une a la colección.
// member of the user control class
private CollectionViewModel collection = new CollectionViewModel();
// in the constructor
listView.ItemSource = collection.Collection.
Esto no filtra nada. Así que tengo estas casillas de verificación y deben indicar qué elementos (dependiendo del estado) se deben mostrar. He utilizado entonces una CollectionViewSource
:
private void UpdateView()
{
var source = CollectionViewSource.GetDefaultView(collection.Collection);
source.Filter = p => Filter((ProjectViewModel)p);
listStatus.ItemsSource = source;
}
El método del filtro se ve así:
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);
}
Esto tiene la desventaja de que captura los valores de las casillas de verificación, por lo que tiene que llamar a este método (UpdateView
) cada vez que se marca una casilla de verificación. Pero funciona.
Sin embargo, el estado del elemento cambia y si "hecho" no está marcado, por ejemplo, cuando un elemento entra en "hecho", debe eliminarse de la vista. Obviamente eso no cambia a menos que vuelva a llamar al UpdateView
. Así que necesito llamar a este método cada vez que algo cambia. Eso me parece feo e ineficiente.
Entonces mi pregunta es, ¿se puede hacer esto de una manera más agradable?
Publiqué otro enfoque como respuesta, pero recuerdo que los filtros funcionan sin una llamada a Update(). Intente implementar NotifyPropertyChanged en Project: el enlace no tiene conocimiento de un cambio sin este. – Paparazzi