5

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

添加到集合中的新项目位于NewItems属性中,即一个IList对象。Intellisense 不会让我访问.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
    }

这个例子使事情尽可能通用,但仍然失败。

4

1 回答 1

4

如果没有一个好的最小、完整和可验证的代码示例,就不可能准确地说出您需要做什么。但与此同时,让我们尝试从您发布的代码中消除您的一些误解:

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是框架中的私有类。您不应该直接使用它。IList这只是NewItems属性返回的实现。这个实现的重要一点是它是只读的。不支持、和等IList成员。你所能做的就是把物品拿出来。但同样重要的是,就您的代码而言,唯一重要的类型是. 你不能直接访问私有类型的成员;它们只能通过它们实现的公共接口使用。Add()Insert()Remove()IList
  3. 您并没有具体说明"Cast failed"的含义。这是不可信的,因为该NewItems属性已经是 type IList。一个演员IList将微不足道地成功。
  4. 确实,您不能强制IList转换为 generic IList<Item>IList您正在处理的实现是私有类System.Collections.ArrayList.ReadOnlyList,它不可能实现通用IList<Item>接口。毕竟,它ReadOnlyList是由 Microsoft 编写的,并且是在 .NET 框架中的。他们怎么知道你的Item类型?
  5. 您不应该Item明确使用对象的属性索引器。这作为隐藏成员存在。相反,您应该使用内置的 C# 语法来索引对象本身。即e.NewItems[0]j[0]
  6. 一旦将 a 分配null给变量i,再多的转换都不会将该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. 如果列表不包含 type 的元素string,则将任何非 null 元素值转换string为都不起作用。

但这些都是代码其余部分特有的问题。您还没有提供,所以我能做的最好的就是尝试笼统地解释您当前似乎误解此事件及其支持类型如何工作的所有方式。

于 2016-08-21T18:55:13.070 回答