I have a handler for the CollectionChanged
event of an ObservableCollection<T>
object, and cannot figure out how to use the NotifyCollectionChangedEventArgs
to retrieve the item contained within the IList
for the event.
New items added to the collection are in the NewItems
property, an IList
object. Intellisense won't let me access .Item[Index]
(which I should be able to according to the docs) nor can I cast the NewItems
list to a local variable (according to debug the NewItems
list is a System.Collections.ArrayList.ReadOnlyList
which doesn't seem to exist as an accessible class in MSDN.)
What am I doing wrong?
Example:
private void ThisCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Item I = e.NewItems._________;//<<<<<cannot access any property to get the item
var j = e.NewItems;//System.Collections.ArrayList.ReadOnlyList, see if you can find in the MSDN docs.
IList I1 = (IList) e.NewItems;//Cast fails.
IList<Item> = (IList<Item>)e.NewItems.________;//<<<<<<<Can't make this cast without an IList.Item[Index] accessor.
var i = j[0]; //null
var ioption = j.Item[0]; //no such accessor
string s = (string)i; //null
}
This example is keeping things as generic as possible and still fails.
Without a good Minimal, Complete, and Verifiable code example it will be impossible to say exactly what you need to do. But in the meantime, let's try to clear up at least some of your misconceptions from the code you posted:
private void ThisCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Item I = e.NewItems._________;//<<<<<cannot access any property to get the item
var j = e.NewItems;//System.Collections.ArrayList.ReadOnlyList, see if you can find in the MSDN docs.
IList I1 = (IList) e.NewItems;//Cast fails.
IList<Item> = (IList<Item>)e.NewItems.________;//<<<<<<<Can't make this cast without an IList.Item[Index] accessor.
var i = j[0]; //null
var ioption = j.Item[0]; //no such accessor
string s = (string)i; //null
}
NotifyCollectionChangedEventArgs.NewItems
is a property, with the type IList
, a non-generic interface. The two key aspects of this interface as it relates to the NewItems
property is that you can get the Count
of items, and you can index the list. Indexing the list returns an object
; it's up to you to cast that to an appropriate type.System.Collections.ArrayList.ReadOnlyList
is a private class in the framework. You are not meant to use it directly. It's simply the implementation of IList
that the NewItems
property returns. The important thing about this implementation is that it's read-only. IList
members like Add()
, Insert()
, and Remove()
are not supported. All you can do is get items out. But just as important is that, as far as your code is concerned, the only type that's important is IList
. You don't get to access members of private types directly; they are usable only through the public interfaces they implement.NewItems
property is already of the type IList
. A cast to IList
would succeed trivially.IList
to the generic IList<Item>
. The implementation of IList
you're dealing with is the private class System.Collections.ArrayList.ReadOnlyList
, which can't possibly implement the generic IList<Item>
interface. After all, the ReadOnlyList
was written by Microsoft and is in the .NET framework. How would they know about your Item
type?Item
property indexer of an object explicitly. This exists as a hidden member. Instead, you're expected to use the built-in C# syntax where you index off the object itself. I.e. e.NewItems[0]
or j[0]
.null
to the variable i
, no amount of casting is going to change that null
value into something else. Not string
, not some other type.You've tried a lot of different things, most of which make no sense so it's not a surprise they don't work. The closest you've gotten would be the j[0]
expression. But you can just use e.NewItems
directly. Your code should look more like this:
private void ThisCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Assumes that the elements in your collection are in fact of type "Item"
Item item = (Item)e.NewItems[0];
// do something with "item"
}
However, it's important to note that you need to first check to see what kind of change has occurred to the collection. The NewItems
list may be empty, if there aren't actually any new items. An element of the list may be null
, if the newly set item value was in fact null
. Whether you can successfully cast a non-null element value to Item
depends on what Item
actually is here, and whether your collection would ever actually have an element of that type in it. Likewise your attempts to cast to string
. If the list doesn't contain elements of type string
, then casting any non-null element value to string
isn't going to work.
But these are all issues that are specific to the rest of the code. You haven't provided that, so the best I can do is try to explain in general terms all of the ways you seem to current misunderstand how this event and its supporting types work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With