Automatically refresh ICollectionView Filter

c#, icollectionview, wpf

Solution

AFAIK there is no inbuilt support in `ICollectionView` to refresh collection on any property change in underlying source collection.

But you can subclass `ListCollectionView` to give it your own implementation to `refresh collection on any property changed`. Sample -

public class MyCollectionView : ListCollectionView
{
    public MyCollectionView(IList sourceCollection) : base(sourceCollection)
    {
        foreach (var item in sourceCollection)
        {
            if (item is INotifyPropertyChanged)
            {
                ((INotifyPropertyChanged)item).PropertyChanged +=
                                                  (s, e) => Refresh();
            }
        }
    }
}

You can use this in your project like this -

Workers = new MyCollectionView(DataManager.Data.Workers);

This can be reused across your project without having to worry to refresh collection on every `PropertyChanged`. `MyCollectionView` will do that `automatically` for you.

OR

If you are using .Net4.5 you can go with `ICollectionViewLiveShaping` implementation as described here.

I have posted the implementation part for your problem here - Implementing ICollectionViewLiveShaping.

Working code from that post -

public ICollectionViewLiveShaping WorkersEmployed { get; set; }

ICollectionView workersCV = new CollectionViewSource
                         { Source = GameContainer.Game.Workers }.View;

ApplyFilter(workersCV);

WorkersEmployed = workersCV as ICollectionViewLiveShaping;
if (WorkersEmployed.CanChangeLiveFiltering)
{
    WorkersEmployed.LiveFilteringProperties.Add("EmployerID");
    WorkersEmployed.IsLiveFiltering = true;
}

Problem

Is there any way to automatically update a filter on an `ICollectionView` without having to call `Refresh()` when a relevant change has been made? I have the following: ``` [Notify] public ICollectionView Workers { get; set; } ``` The [Notify] attribute in this property just implements `INotifyPropertyChanged` but it doesn't seem to be doing anything in this situation. ``` Workers = new CollectionViewSource { Source = DataManager.Data.Workers }.View; Workers.Filter = w => { Worker worker = w as Worker; if (w == null) return false; return worker.Employer == this; }; ``` In XAML: ``` <TextBlock x:Name="WorkersTextBlock" DataContext="{Binding PlayerGuild}" FontFamily="Pericles" Text="{Binding Workers.Count, StringFormat=Workers : {0}, FallbackValue=Workers : 99}" /> ``` Update: It looks like using `ICollectionView` is going to be necessary for me, so I'd like to revisit this topic. I'm adding a bounty to this question, the recipient of which will be any person who can provide some insight on how to implement a 'hands-off' `ICollectionView` that doesn't need to be manually refreshed. At this point I'm open to any ideas.

Original source

Related problems