#986 – Filtering a ListBox Using a CollectionViewSource
January 14, 2014 5 Comments
When populating a ListBox from a CollectionViewSource, you can also filter the data. Below is an example of a ListBox that is bound to a CollectionViewSource.
<Window.Resources> <CollectionViewSource x:Key="cvsActors" Source="{Binding ActorList}" > <CollectionViewSource.SortDescriptions> <scm:SortDescription PropertyName="LastName" /> </CollectionViewSource.SortDescriptions> </CollectionViewSource> </Window.Resources> <StackPanel> <ListBox Name="lbActors" Margin="15" Width="200" Height="200" ItemsSource="{Binding Source={StaticResource cvsActors}}"/> <CheckBox Content="Only Joans" IsChecked="{Binding OnlyJoans}" Margin="15"/> </StackPanel>
In code, we add a handler for the Filter event of the CollectionViewSource. The handler is called for each item in the list.
// Requires: using System.Windows.Data ((CollectionViewSource)this.Resources["cvsActors"]).Filter += ActorList_Filter;
In the handler, we set the Accepted property of the argument if the item should be included in the list.
void ActorList_Filter(object sender, FilterEventArgs e) { // Set e.Accepted to true to include the item in the list if (!onlyJoans) e.Accepted = true; else { Actor a = e.Item as Actor; e.Accepted = (a.FirstName == "Joan") ? true : false; } }
We also have to make sure to “refresh” the CollectionViewSource when the OnlyJoans property changes. This will trigger it to re-filter the collection.
private bool onlyJoans; public bool OnlyJoans { get { return onlyJoans; } set { if (value != onlyJoans) { onlyJoans = value; RaisePropertyChanged("OnlyJoans"); ((CollectionViewSource)this.Resources["cvsActors"]).View.Refresh(); } } }
Pingback: #989 – Enabling Live Filtering in a CollectionViewSource | 2,000 Things You Should Know About WPF
In .NET 4.6.2 (the version I attempted to use this approach on) Filter is not a direct property of a CollectionViewSource. Rather, I used the following code-behind snippet, where “cvs” is a CollectionViewSource defined in XAML:
Dim cvs As CollectionViewSource = DirectCast(Resources(“”), CollectionViewSource)
AddHandler cvs.Filter, AddressOf
The example in this post does work just fine in 4.6.2. Note that Filter was never a property of CollectionViewSource. It’s an event and in my code-behind example, I’m attaching a handler to it. It looks like you’re doing the same thing, only in VB.NET rather than C#.
Good day! I’m just learning WPF. Do you have a complete example. Because it is not clear what is in Actor.
You can find the code in other posts on the blog.