18

我编写了一个带有搜索扩展名的自定义 WPF 控件,我们将其命名为MyControl. Control 是一个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);
}

过滤源集合的视图(从而将其显示在内部列表框中)。

现在假设我们在 XAML 中定义了 10 个具有相同 DynamicSource 的 MyControl。问题是,如果其中一个对源集合应用过滤器,它也会影响所有其他实例。

您将如何更改控件以避免这种行为?

4

2 回答 2

40

在这种情况下,您通常希望为集合的每个不同过滤使用创建一个单独的 ICollectionView 实例。使用 ICollectionView 的特定实现不是一个好主意,因为如果 ItemsSource 绑定到不同类型的集合,则可能需要更改 CollectionView 类型。使用

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

将自动为您提供正确类型的 ICollectionView。

不幸的是,在这种情况下,您可能会发现很难将不同的集合应用于自定义控件的 ItemsPresenter,因为所有这些魔法都是由基础 ItemsControl 类为您完成的,并且依赖于 ItemsSource/Items 属性它管理。当使用类似于 ItemsControl 的默认模板时会发生这种情况。

如果您实际上在 ControlTemplate 中使用单独的 ListBox 控件(如果需要,还使用 ​​TemplateBinding 所有 ItemsSource 属性),那么您应该能够简单地在您的控件上添加一个新的 ICollectionView DP(我建议只读)保存您过滤后的集合版本,并将模板 ListBox 的 ItemsSource 绑定到该新属性。

于 2010-01-29T16:51:48.370 回答
5

存在的问题是对于给定的源CollectionViewSource.GetDefaultView(object)将始终返回相同的ICollectionView实例,这是任何ItemsControl扩展在显示该源时将使用的。

您可以通过创建一个新实例来解决此问题,ICollectionView供您希望能够独立过滤集合的每个控件使用,然后将ItemsSource每个控件的属性显式绑定到该特定视图。所需的类型ICollectionView取决于您的方案,但ListCollectionView通常是合适的。

于 2010-01-29T13:40:28.000 回答