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. Проблема заключается в том, что если один из них применяет фильтр к исходной коллекции, это повлияет и на все остальные экземпляры.
Как бы вы изменили контроль, чтобы избежать такого поведения?
2 ответа
В подобных ситуациях обычно требуется создать отдельный экземпляр 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 с этим новым свойством.
Проблема в том, что CollectionViewSource.GetDefaultView(object)
всегда будет возвращаться одинаково ICollectionView
экземпляр для данного источника, и это то, что любой ItemsControl
расширение будет использовать при отображении этого источника.
Вы можете обойти это, создав новый экземпляр ICollectionView
использоваться каждым элементом управления, который вы хотите иметь возможность независимо фильтровать коллекцию, а затем явно связывать ItemsSource
Свойство каждого элемента управления для этого конкретного представления. Тип ICollectionView
необходимо будет зависеть от вашего сценария, но ListCollectionView
как правило, уместно.