INotifyCollectionChanged's NewItems - cannot use OfType<T> to get data
Asked Answered
S

2

5

I am attempting to get some custom objects from the CollectionChanged event of a collection which implements INotifyCollectionChanged.

MyControl_MyCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
  if(e.Action == NotifyCollectionChangedAction.Add)
  {
    lock(e.NewItems.SyncRoot)
    {
      var myItems = e.NewItems.OfType<MyType>();

      if(myItems.Any())
      {
        //do stuff
      }
    }
  }
}

The problem I am facing is that myItems always says "Enumeration yielded no results".

Expanding on debug e.NewItems.SyncRoot shows the following:

e.NewItems.SyncRoot | {object[1]}
|-[0] | {System.Linq.Enumerable.WhereSelectListIterator<MyType, IMyInterface>}
| |-base ...
| |-Non-public members
| |-Results View | Expanding the Results View...
|   |-[0] | MyType

So clearly the data is there. What is the method for retrieving this data?

Seclusive answered 8/10, 2012 at 11:23 Comment(2)
Side note: use .Any() instead of .Count() > 0. You don't care how many items you have (at that point), so why bother counting them all?Stephaniastephanie
A fair point, will edit.Seclusive
S
8

This looks like a bug in whatever is creating the NotifyCollectionChangedEventArgs object.

NotifyCollectionChangedEventArgs has several constructors. There are two relevant ones here:

  • NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction, object)
  • NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction, IList)

The first describes a change on a single item. The second describes a change on a list of items.

However, the NotifyCollectionChangedEventArgs constructor has been called as new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, enumerable). IEnumerable<...> does not implement IList, so the first constructor gets called when the second is the one that should be used.

Do you have control over the code that raises NotifyCollectionChanged? If so, use new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, enumerable.ToList()) instead.

Stephaniastephanie answered 8/10, 2012 at 11:40 Comment(1)
You sir, are a genious. This was exactly the problem. Thank you.Seclusive
B
1

So clearly the data is there

It is clear, that your collection, that was changed, contains items of type System.Linq.Enumerable.WhereSelectListIterator<MyType, IMyInterface>, not a MyType type.

Brain answered 8/10, 2012 at 11:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.