Igor Mikushkin
Igor Mikushkin

Reputation: 1317

Chaining CollectionViewSource

I'd like to chain two CollectionViewSources in WPF application. Is there any way to make following things work?

MainWindow.xaml.cs:

using System.Collections.Generic;
using System.Linq;
using System.Windows;

namespace ChainingCollectionViewSource
{
  public partial class MainWindow : Window
  {
    public IEnumerable<int> Items => Enumerable.Range(0, 10);
    public MainWindow()
    {
      DataContext = this;
      InitializeComponent();
    }
  }
}

MainWindow.xaml:

<Window x:Class="ChainingCollectionViewSource.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Resources>
        <CollectionViewSource x:Key="ItemsViewA"
                              Source="{Binding Items}" />
        <CollectionViewSource x:Key="ItemsViewB"
                              Source="{Binding Source={StaticResource ItemsViewA}}" />
    </Window.Resources>
    <ListBox ItemsSource="{Binding Source={StaticResource ItemsViewB}}" />
</Window>

Upvotes: 1

Views: 199

Answers (1)

mm8
mm8

Reputation: 169150

A CollectionViewSource doesn't filter its source collection, it filters the view. Whenever you bind to some collection of data in WPF, you are always binding to an automatically generated view and not to the actual source collection itself. A view is a class that implements the System.ComponentModel.ICollectionView interface and provides functionality to sort, filter, group and keeping track of the current item in a collection.

So instead of trying to "chaining" two CollectionViewSources together you should bind them to the same source collection:

<CollectionViewSource x:Key="ItemsViewA" Source="{Binding Items}" />
<CollectionViewSource x:Key="ItemsViewB" Source="{Binding Items}" />

They can then filter the views independently of each other.

If you want to apply control B's filters on top of control A's filters, you should implement this logic in the Filter event handler of the CollectionViewSource, e.g.:

private void ItemsViewA_Filter(object sender, FilterEventArgs e)
{
    e.Accepted = Include(e.Item as YourType);
}

private bool Include(YourType obj)
{
    //your filtering logic...
    return true;
}

private void ItemsViewB_Filter(object sender, FilterEventArgs e)
{
    var item = e.Item as YourType;
    e.Accepted = Include(item) && /* your additional filtering logic */;
}

Upvotes: 2

Related Questions