2016-08-21 125 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處的元素。您應該更喜歡直接使用擴展方法進行索引。 –