WPF CollectionViewSource Несколько просмотров? - PullRequest
17 голосов
/ 29 января 2010

Я написал пользовательский элемент управления WPF с расширением поиска, назовем его MyControl. Элемент управления является потомком класса ItemsControl.

Итак, я передаю источник данных следующим образом:

Сам элемент управления использует

protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
{
    if (newValue != null)
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
        view.Filter += this.FilterPredicate;
    }

    if (oldValue != null)
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);
        view.Filter -= this.FilterPredicate;
    }

    base.OnItemsSourceChanged(oldValue, newValue);
}

, чтобы отфильтровать представление исходной коллекции (отображая ее во внутреннем ListBox).

Теперь предположим, что у нас есть 10 таких MyControls, определенных в XAML с одним и тем же DynamicSource. Проблема заключается в том, что если один из них применяет фильтр к исходной коллекции, это повлияет и на все остальные экземпляры.

Как бы вы изменили элемент управления, чтобы избежать такого поведения?

Ответы [ 2 ]

38 голосов
/ 29 января 2010

В подобных ситуациях обычно требуется создать отдельный экземпляр ICollectionView для каждого использования коллекции с разной фильтрацией.Не рекомендуется использовать конкретную реализацию ICollectionView, поскольку возможно изменение типа CollectionView, если ItemsSource связан с другим типом коллекции.Использование

 ICollectionView filteredView = new CollectionViewSource { Source=newValue }.View;

автоматически предоставит ICollectionView правильного типа.

К сожалению, в этом случае вы можете обнаружить, что очень трудно применить другую коллекцию к ItemsPresenter.вашего пользовательского элемента управления, поскольку вся эта магия выполняется для вас базовым классом ItemsControl и зависит от свойств ItemsSource / Items, которыми он управляет.Это происходит при использовании чего-то похожего на шаблон по умолчанию ItemsControl.

Если вы на самом деле используете отдельный элемент управления ListBox (и TemplateBinding все свойства ItemsSource, если они вам нужны) внутри ControlTemplate, то вы можете просто добавитьновый DP ICollectionView (я бы порекомендовал только для чтения) на вашем элементе управления для хранения отфильтрованной версии коллекции и привязки ItemsSource шаблона ListBox к этому новому свойству.

5 голосов
/ 29 января 2010

Проблема в том, что CollectionViewSource.GetDefaultView(object) всегда будет возвращать один и тот же экземпляр ICollectionView для данного источника, и это то, что любое расширение ItemsControl будет использовать при отображении этого источника.

Вы можете обойти это, создав новый экземпляр ICollectionView, который будет использоваться каждым элементом управления, для которого вы хотите иметь возможность независимо фильтровать коллекцию, а затем явно связать свойство ItemsSource каждого элемента управления с этим конкретным Посмотреть. Необходимый тип ICollectionView будет зависеть от вашего сценария, но обычно подходит ListCollectionView.

...