Question

I have a ListBox which I am loading with objects of three types which all inherit from the same parent type. I would like to filter out the objects in the ListBox based on their type using a CollectionViewSource but I am having trouble writing the filter(s).

My XAML is as follows:

<UserControl.Resources>
    <CollectionViewSource x:Key="eventsViewSource" 
                          Source="{Binding lifeCycleEvents}" >
        <CollectionViewSource.SortDescriptions>
            <compMod:SortDescription PropertyName="Date" Direction="Ascending"/>
        </CollectionViewSource.SortDescriptions>
    </CollectionViewSource>
</UserControl.Resources>


<ListBox Name="lstEventHistory"  ItemsSource="{Binding Source={StaticResource eventsViewSource}}">
...
</ListBox>

In the code-behind I'm loading an observable collection of the objects returned from an async method call:

private ObservableCollection<LifeCycleEvent> lifeCycleEvents;

...
                lifeCycleEvents= e.Result; 
                CollectionViewSource eventsViewSource = this.Resources["eventsViewSource"] as CollectionViewSource;
                eventsViewSource.Source = lifeCycleEvents;

Now I would like to write a filter that will only show objects of a certain type based on checkboxes the user will click in the UI.

The following is a failed attempt at writing one filter:

eventsViewSource.Filter = new Predicate<object>(rmaFilter);

public bool rmaFilter(object item)
     {
        if(item.GetType() == typeof(RmaEvent))
            return true;
        else 
            return false;
     }

This gives the following error: "The event System.Windows.Data.CollectionViewSrouce.Filter can only appear on the left hand side of += or -=".

I haven't been able to find any tutorials that do exactly what I need. Those that do, depend on a default view which doesn't exist in Silverlight. One such tutorial I looked at can be found here

Any tips are appreciated!

Was it helpful?

Solution

The Filter property of CollectionView and CollectionViewSource is an event and contains a collection of type FilterEventHandler, not Predicate. Each event handler is called for each item in the CollectionView to determine if it should be displayed or not.

Also, the addition or removal of event handlers from the Filter property will cause the event handlers to be called and the collection updated.

So the correct code for wiring up the Filter event handlers is:

eventsViewSource.Filter += new FilterEventHandler(rmaFilter);

And to remove it:

eventsViewSource.Filter -= new FilterEventHandler(rmaFilter);

And the new handler:

public void rmaFilter(object sender, FilterEventArgs args)
 {
    args.Accepted = args.Item is RmaType;
 }

OTHER TIPS

According to MSDN documentation, Filter is a an event in CollectionViewSource type. So? the correct syntax is:

eventsViewSource.Filter += new Predicate<object>(rmaFilter);

In tutorial, you've link above, author used static method of the CollectionViewSource type, which returns a CollectionView object. This CollectionView object has Filter property (not event yet!) and you can assign Filter delegate to it, using = syntax

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top