开发者

WPF: ICollectionView - Filter one list if item is contained in another list?

Basically, I have 2 ListView's each binding to a different ItemsSource.

List 1 can not be changed (it's a ReadOnlyObservableCollection).

List 2 can be changed (through user interaction).

I need to add a filter to List 1 so that it doesn't display anything that's found in List 2. This is my code so far...

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


List2.ItemsSource comes back as an IEnumerable instead of ObservableCollection (what it really is). I want to do this as efficiently as possible, so I wasn't sure if I should:

  1. Explicitly Cast the ItemsSource as a IList to gain access to Contains?
  2. Iterate through the the ItemsSource myself to see if it contains the item?
  3. Use LINQ's Cast extension method to cast to an IList (or some other type) to gain access to Contains?
  4. Any other way?

UPDATE:

It doesn't seem to continue filtering items after the first time it renders:

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开发者_StackOverflow.Contains(item); //Shows all items, but as I add items
                                       //to list 2 it doesn't filter items out of
                                       //list 1.
};

UPDATE 2:

I think I understand why it's not reapplying the filter. The original collection is not raising a CollectionChanged notification, so it doesn't bother to run the filter again. Perhaps solving this part is better suited as a different question? But, in case anyone wants to answer it here:

How can I get my List1 to reapply the filter when the List2 collection changes?

UPDATE 3: I asked how to tie into the collectionchanged event in a separate SO question and got my answer.


ItemsSource is statically declared as an IEnumerable, but its actual runtime type can be anything that implements IEnumerable. If you happen to know that it's actually an ObservableCollection<MyItem>, you can just cast to this type:

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

(or you can just cast to IList<MyItem>, since Contains is defined in this interface)

Linq is also a good option:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜