WPF:ICollectionView - 如果项目包含在另一个列表中,则筛选一个列表?

时间:2011-04-27 14:03:32

标签: wpf listview filter itemssource icollectionview

基本上,我有2个ListView,每个都绑定到不同的ItemsSource

列表1 无法更改(它是ReadOnlyObservableCollection) 列表2 可以更改(通过用户交互)。

我需要在List 1中添加一个过滤器,这样它就不会显示List 2中的任何内容。这是我到目前为止的代码......

view = CollectionViewSource.GetDefaultView(List1.ItemsSource);
view.Filter += o =>
{
    MyItem item = o as MyItem;
    return List2.ItemsSource.??;
};

<小时/> List2.ItemsSource以IEnumerable而不是ObservableCollection(实际上是什么)的形式返回。我想尽可能高效地做到这一点,所以我不确定是否应该:

  1. 明确地将ItemsSource转换为IList以获取对Contains的访问权限?
  2. 自己遍历ItemsSource以查看它是否包含该项目?
  3. 使用LINQ的Cast扩展方法转换为IList(或其他类型)以获取对Contains的访问权限?
  4. 还有其他方式吗?

  5. 更新:

    第一次呈现后似乎没有继续过滤项目:

    view = CollectionViewSource.GetDefaultView(List1.ItemsSource);
    view.Filter += o =>
    {
        MyItem item = (MyItem)o;
        var collection = (ObservableCollection<MyItem>)List2.ItemsSource;
        //return collection.Contains(item);//Filters out ALL items from the list
        return !collection.Contains(item); //Shows all items, but as I add items
                                           //to list 2 it doesn't filter items out of
                                           //list 1.
    };
    

    更新2:

    我想我明白为什么它没有重新应用过滤器。原始集合不会引发CollectionChanged通知,因此它不会再次运行过滤器。也许解决这一部分更适合作为一个不同的问题?但是,如果有人想在这里回答:

    如何在List2集合更改时让我的List1重新应用过滤器?

    更新3: 我问如何在separate SO question中加入collectionchanged事件并得到我的回答。

1 个答案:

答案 0 :(得分:1)

ItemsSource被静态声明为IEnumerable,但其实际运行时类型可以是实现IEnumerable的任何内容。如果您碰巧知道它实际上是ObservableCollection<MyItem>,您可以转换为此类型:

view = CollectionViewSource.GetDefaultView(List1.ItemsSource);
view.Filter += o =>
{
    MyItem item = (MyItem)o;
    var collection = (ObservableCollection<MyItem>)List2.ItemsSource;
    return collection.Contains(item);
};

(或者您可以转换为IList<MyItem>,因为此界面中定义了Contains

Linq也是一个不错的选择:

view = CollectionViewSource.GetDefaultView(List1.ItemsSource);
view.Filter += o =>
{
    MyItem item = (MyItem)o;
    return List2.ItemsSource.Cast<MyItem>().Contains(item);
};