1

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

列表 1不能更改(它是 a ReadOnlyObservableCollection)。
清单 2可以更改(通过用户交互)。

我需要在列表 1 中添加一个过滤器,这样它就不会显示在列表 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. 还有什么办法吗?

更新:

第一次渲染后,它似乎没有继续过滤项目:

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:我在一个单独的SO问题 中询问了如何与collectionchanged事件联系起来并得到了我的答案。

4

1 回答 1

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);
};
于 2011-04-27T14:12:08.880 回答