List Filtering in WPF with M-V-VM
The first Windows Forms application I ever wrote was an anagram generator back in 2002. As part of my ongoing efforts to learn WPF and M-V-VM, I have been porting it to WPF, and adding a few new features along the way. Today, I wanted to add a TextBox
that would allow you filter the anagram results to only show results that contained a specific sub-string.
The first task is to create a TextBox
and a ListBox
in XAML and set their binding properties. We want the filter to update every time a user types a character in, so we use the UpdateSourceTrigger
to specify this.
<TextBox Margin="5"
Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}"
Width="150" />
...
<ListBox Margin="5" ItemsSource="{Binding Phrases}" />
Now we need to create the corresponding Filter and Phrases properties in our ViewModel
. Then we need to get an ICollectionView based on our ObservableCollection
of phrases. Once we have done this, we can attach a delegate to it that will perform our filtering. The final step is to call Refresh on the view whenever the user changes the filter box.
private ICollectionView phrasesView;
private string filter;
public ObservableCollection<string> Phrases { get; private set; }
public AnagramViewModel()
{
...
Phrases = new ObservableCollection<string>();
phrasesView = CollectionViewSource.GetDefaultView(Phrases);
phrasesView.Filter = o => String.IsNullOrEmpty(Filter) ? true : ((string)o).Contains(Filter);
}
public string Filter
{
get
{
return filter;
}
set
{
if (value != filter)
{
filter = value;
phrasesView.Refresh();
RaisePropertyChanged("Filter");
}
}
}
And that's all there is to it. It can be kept nicely encapsulated within the ViewModel
without the need for any code-behind in the view.
Comments
How do you get the listbox to refresh? I put the code in like you have and I see that it is filtering but doesnt show the new data?
FayeHow does the listbox get refreshed. I have it where I see that the data is filtered but it doesnt display the new filtered data?
Fayesee the code fragment above: phrasesView.Refresh
Mark HVery useful for my project. Thank you!
SanderGreat article!!
TammarThis is wrong: you need to bind to the ICollectionView and not to the ObservableCollection to see the filtering effect.
GiulioThis doesn't work
xmichael911