2016-08-21 123 views
2

我对CollectionChanged事件的ObservableCollection<T>对象的处理程序,并不能弄清楚如何使用NotifyCollectionChangedEventArgs检索包含IList的事件内的项目。NotifyCollectionChangedEventArgs项目无法访问

添加到集合中的新项目位于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 
    } 

这个例子是保持事物尽可能通用,并且仍然会失败。

+0

您应该提供[最小,完整和可验证示例](http://stackoverflow.com/help/mcve)以获得更好的帮助。 –

回答

1

没有一个好的Minimal, Complete, and Verifiable code 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 
} 
  1. NotifyCollectionChangedEventArgs.NewItems是一个属性,与该类型IList,非通用接口。该界面的两个关键方面与NewItems属性相关,您可以获得项目的Count,并且您可以为列表编制索引。索引列表返回object;这取决于你将其转换为适当的类型。
  2. System.Collections.ArrayList.ReadOnlyList是框架中的私有类。你不打算直接使用它。这只是执行IListNewItems属性返回。这个实现的重要之处在于它是只读的。 IList不支持Add()Insert()Remove()等成员。你所能做的就是把物品拿出来。但同样重要的是,就您的代码而言,唯一重要的是IList。你不能直接访问私有类型的成员;它们只能通过它们实现的公共接口使用。
  3. 您没有具体说明您的意思是“Cast failed”。这将是不合情理的,因为NewItems属性已经是IList类型。演员到IList会平凡成功。
  4. It is确实无法将IList转换为通用IList<Item>。你正在处理的IList的实现是私有类System.Collections.ArrayList.ReadOnlyList,它不可能实现通用的IList<Item>接口。毕竟,ReadOnlyList是由Microsoft编写的,并且位于.NET框架中。他们如何知道你的Item类型?
  5. 您不打算明确使用对象的Item属性索引器。这存在为隐藏成员。相反,您需要使用内置的C#语法来索引对象本身。即e.NewItems[0]j[0]
  6. null分配给变量i后,没有任何投射量会将该值更改为其他值。不是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不会起作用。

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

+0

感谢您的回复,您的代码片段非常完美。我可以看到我在考虑将NewItems作为一种方法而不是一个列表。为了纠正我的误解,为什么ObservableCollection实现IEnumerable(允许扩展方法.ElementAt(index)),但args实现IList(不允许ElementAt)。我认为这可能是我混乱的根源。 – NWoodsman

+0

'INotifyCollectionChanged'不是通用的;它需要与任何类型的集合一起工作,包括非通用情景。所以通用'ElementAt (int)'方法不能在那里使用。请注意,虽然您可以在“ObservableCollection ”实例上调用“ElementAt (int)”,但不需要直接编制“ObservableCollection ”对象。 'myObservableCollection [17];'获取索引17处的元素。您应该更喜欢直接使用扩展方法进行索引。 –