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.