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?

dav_i
  • 25,285
  • 17
  • 94
  • 128
  • 1
    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? –  Oct 08 '12 at 11:35
  • A fair point, will edit. – dav_i Oct 08 '12 at 11:36

2 Answers2

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.

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.

Dennis
  • 34,925
  • 9
  • 72
  • 134