Ho un controllo ListView
che visualizza elementi da una raccolta osservabile. Questi articoli devono essere filtrati. Sono in grado di farlo con un CollectionViewSource
, ma il filtro deve essere aggiornato ogni volta che un elemento cambia.Filtra una raccolta osservabile
miei articoli assomiglia a questo:
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; }
}
}
Poi ho questa ListView
cui ItemSource
è legato alla raccolta.
// member of the user control class
private CollectionViewModel collection = new CollectionViewModel();
// in the constructor
listView.ItemSource = collection.Collection.
Questo non filtra nulla. Quindi ho queste caselle di controllo e dovrebbero indicare quali elementi (a seconda dello stato) dovrebbero essere visualizzati. Ho usato poi un CollectionViewSource
:
private void UpdateView()
{
var source = CollectionViewSource.GetDefaultView(collection.Collection);
source.Filter = p => Filter((ProjectViewModel)p);
listStatus.ItemsSource = source;
}
Il metodo del filtro si presenta così:
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);
}
Questo ha lo svantaggio che cattura i valori delle caselle di controllo, quindi devo chiamare questo metodo (UpdateView
) ogni volta che viene selezionata una casella di controllo. Ma funziona.
Tuttavia, lo stato dell'elemento cambia e se "done" non viene controllato, ad esempio, quando un elemento va in "done" dovrebbe essere rimosso dalla vista. Ovviamente ciò non cambia a meno che non chiami ancora UpdateView
. Quindi ho bisogno di chiamare questo metodo ogni volta che qualcosa cambia. Mi sembra brutto e inefficiente.
Quindi la mia domanda è: è possibile farlo in un modo più bello?
Ho inviato un altro approccio come risposta, ma ricordo che i filtri funzionano senza una chiamata ad Update(). Prova ad implementare NotifyPropertyChanged in Project - l'associazione non è a conoscenza di una modifica senza di essa. – Paparazzi