Подтвердить что ты не робот

WPF CollectionViewSource несколько просмотров?

Я написал собственный элемент управления 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. Проблема заключается в том, что если один из них применит фильтр к исходной коллекции, это затронет и все остальные экземпляры.

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

4b9b3361

Ответ 1

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

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

даст вам ICollectionView, что правильный тип будет автоматически.

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

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

Ответ 2

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

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