Автоматическое обновление фильтра ICollectionView

Есть ли способ автоматического обновления фильтра на ICollectionView без вызова Refresh(), когда было сделано соответствующее изменение?

У меня есть следующее:

[Notify]
public ICollectionView Workers { get; set; }

Атрибут [Notify] в этом свойстве реализует только INotifyPropertyChanged, но в этой ситуации он ничего не делает.

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

В XAML:

<TextBlock x:Name="WorkersTextBlock"
           DataContext="{Binding PlayerGuild}"
           FontFamily="Pericles"
           Text="{Binding Workers.Count,
                          StringFormat=Workers : {0},
                          FallbackValue=Workers : 99}" />

Обновление: Похоже, что использование ICollectionView будет необходимо для меня, поэтому я хотел бы вернуться к этой теме. Я добавляю щедрость к этому вопросу, получателем которого будет любой человек, который может дать некоторое представление о том, как реализовать "hands-off" ICollectionView, который не нужно обновлять вручную. На данный момент я открыт для любых идей.

Ответ 1

AFAIK нет встроенной поддержки в ICollectionView для обновления коллекции при любом изменении свойства в исходной коллекции.

Но вы можете подклассифицировать ListCollectionView, чтобы придать его собственной реализации refresh collection on any property changed. Образец -

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

Вы можете использовать это в своем проекте следующим образом:

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

Это можно использовать повторно в своем проекте, не беспокоясь об обновлении коллекции на каждом PropertyChanged. MyCollectionView сделает это automatically для вас.

ИЛИ

Если вы используете .Net4.5, вы можете пойти с реализацией ICollectionViewLiveShaping, как описано здесь.

Я разместил часть реализации для вашей проблемы здесь - Внедрение ICollectionViewLiveShaping.

Рабочий код из этого сообщения -

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

Ответ 2

Для .Net 4.5: Существует новый интерфейс, который может помочь в достижении этой функции: ICollectionViewLiveShaping.

От Ссылка MSDN:

Когда включена сортировка, группировка или фильтрация в реальном времени, CollectionView изменит положение данных в CollectionView, когда данные изменены. Например, предположим, что приложение использует DataGrid для перечисления акций на фондовом рынке, а акции сортируются по стоимость акций. Если в коллекции CollectionView включена активная сортировка, позиция запаса в DataGrid перемещается, когда значение запаса становится больше или меньше другой стоимости акций.

Дополнительная информация по интерфейсу выше: http://www.jonathanantoine.com/2011/10/05/wpf-4-5-%E2%80%93-part-10-live-shaping/


Для .Net 4 и ниже: Существует еще одна публикация по SO QA, которая может помочь вам: Фильтр CollectionViewSource не обновляется при изменении источника