Filter an ObservableCollection with a CollectionView in C#
Using an ObservableCollection and need to filter its contents? A quick and easy way I found was to create and bind to a CollectionView to perform the filtering for you.
Step 1 : Create the Observable Collection
The first step is to create the observable collection. This will work for objects or system type lists, so feel free to use what you like.
private ObservableCollection<Car> _CarList; public ObservableCollection<Car> CarList { get { if (_CarList == null) { //Code to build the list } return _CarList; } }
Step 2 : Create the Filter
The next step is to create the filter. Simple enough, create a method that returns a boolean and takes an object as a parameter, a predicate. Perform what checks are needed within the filter and return whether it should be shown or not. Here in this example I’m checking to see if another property, FilterText (Just a property that contains the text you want to filter with), and seeing if the name of the model of the car matches.
private bool CarFilter(object item) { Car car = item as Car; if(car.Name.Contains(FilterText)) { return true; } else { return false; } }
Step 3 : Bind and Create the CollectionView
The final step is to set up the adding and binding to the CollectionView, then adding the filter. Let’s first create the CollectionView :
private ICollectionView _CarListView { get; set; }
Next lets set up the binding. Add this at the bottom of the null check in your ObservableCollection set. This will hook up your collection to your view, then add the filter afterwards.
//For the car filtering this._CarListView = CollectionViewSource.GetDefaultView(_CarList); this._CarListView.Filter = CarFilter;
Now let’s see what it looks like all together :
private ICollectionView _CarListView { get; set; } private ObservableCollection<Car> _CarList; public ObservableCollection CarList { get { if (_CarList == null) { //Code to build the list //For the car filtering this._CarListView = CollectionViewSource.GetDefaultView(_CarList); this._CarListView.Filter = CarFilter; } return _CarList; } } private bool CarFilter(object item) { Car car = item as Car; if(car.Name.Contains(FilterText)) { return true; } else { return false; } }
Well, I hope this helps trying to add filtering to an observable collection. Good luck and happy coding!
This is a very nice, clear article. Thank you for creating it. I was eager to try this on my own project, since I desperately need some sort of filtering capability. Unfortunately, when I tried it using Silverlight 5, I get an error message saying there was no definition of GetDefaultView within CollectionViewSource. I searched for some explanations of why this might be happening, and I’m not sure — based on what I found — but it seems that that definition indeed no longer exists. If that’s so, perhaps you might want to add a note to that effect in your article.
Thank you.
amending this line
this._CarListView = CollectionViewSource.GetDefaultView(_CarList);
to
this._CarListView = (Collection)CollectionViewSource.GetDefaultView(_CarList);
worked for me
Thanks a lot! That was exactly what I was looking. It works like a charm!
Thanks a lot! Really helped in WPF. But is there something similar for WinRT
I want to convert the view to an obervable Collection. How can i do it after these steps
I’m not for sure why you would want to since the observable collection is bound to the view?