NotifyCollectionChangedEventArgs项目不可访问

本文关键字:访问 项目 NotifyCollectionChangedEventArgs | 更新日期: 2023-09-27 18:03:16

我有一个ObservableCollection<T>对象的CollectionChanged事件的处理程序,并且无法弄清楚如何使用NotifyCollectionChangedEventArgs来检索事件中包含在IList中的项目。

添加到集合中的新项目位于NewItems属性中,IList对象。智能感知不会让我访问.Item[Index](我应该能够根据文档),也不能将NewItems列表转换为局部变量(根据调试NewItems列表是System.Collections.ArrayList.ReadOnlyList,它似乎不存在作为MSDN中可访问的类)

我做错了什么?

的例子:

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项目不可访问

如果没有一个好的最小化、完整和可验证的代码示例,就不可能确切地说明您需要做什么。但与此同时,让我们试着至少从你发布的代码中澄清一些误解:

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
}
  1. NotifyCollectionChangedEventArgs.NewItems是一个属性,类型为IList,是一个非泛型接口。这个接口与NewItems属性相关的两个关键方面是,您可以获得项目的Count,并且可以对列表进行索引。索引列表返回一个object;你可以把它转换成合适的类型。
  2. System.Collections.ArrayList.ReadOnlyList是框架中的私有类。您不应该直接使用它。NewItems属性返回的只是IList的实现。这个实现的重要之处在于它是只读的。不支持Add()Insert()Remove()IList成员。你能做的就是把东西拿出来。但同样重要的是,就您的代码而言,唯一重要的类型是IList。你不能直接访问私有类型的成员;它们只能通过它们实现的公共接口使用。
  3. 你没有具体说明"Cast fails"是什么意思。这是不可能的,因为NewItems属性已经是IList类型了。强制转换到IList将很容易成功。
  4. 真的,你不能将IList转换为通用的IList<Item>。您正在处理的IList的实现是私有类System.Collections.ArrayList.ReadOnlyList,它不可能实现通用的IList<Item>接口。毕竟,ReadOnlyList是由微软编写的,使用的是。net框架。他们怎么知道你的Item类型?
  5. 你不能显式地使用对象的Item属性索引器。它作为隐藏成员存在。相反,您应该使用内置的c#语法,在该语法中索引对象本身。即e.NewItems[0]j[0]
  6. 一旦你给变量i分配了一个null,再多的强制转换也不会把null的值改变成别的东西。不是string,也不是其他类型。

你已经尝试了很多不同的事情,其中大部分都没有意义,所以它们不起作用并不奇怪。最接近的是j[0]表达式。但是您可以直接使用e.NewItems。您的代码应该看起来更像这样:

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"
}

然而,重要的是要注意,您需要首先检查集合发生了什么样的更改。如果实际上没有任何新项,NewItems列表可能为空。如果新设置的项值实际上是null,则列表中的元素可以是null。是否可以成功地将非空元素值强制转换为Item取决于Item在这里实际是什么,以及您的集合中是否实际上有该类型的元素。同样,您的尝试转换为string。如果列表不包含string类型的元素,那么将任何非空元素的值强制转换为string都将不起作用。

但是这些都是特定于其余代码的问题。你还没有提供,所以我能做的最好的就是试着用一般的术语解释你目前似乎对这个事件及其支持类型如何工作的所有误解。