#986 – Filtering a ListBox Using a CollectionViewSource

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;
            }
        }

986-001
986-002

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();
                }
            }
        }

Advertisement

About Sean
Software developer in the Twin Cities area, passionate about software development and sailing.

5 Responses to #986 – Filtering a ListBox Using a CollectionViewSource

  1. Pingback: #989 – Enabling Live Filtering in a CollectionViewSource | 2,000 Things You Should Know About WPF

  2. Roger Schlueter says:

    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

    • Sean says:

      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#.

  3. Igor says:

    Good day! I’m just learning WPF. Do you have a complete example. Because it is not clear what is in Actor.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: