2016-08-21 2 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 является частным классом в рамках. Вы не должны использовать его напрямую. Это просто реализация IList, которая возвращает свойство NewItems. Важная вещь в этой реализации заключается в том, что она доступна только для чтения. IList таких участников, как Add(), Insert() и Remove() не поддерживаются. Все, что вы можете сделать, это получить предметы. Но так же важно то, что, насколько ваш код имеет значение, единственным важным типом является IList. Вы не можете напрямую обращаться к частным лицам; они могут использоваться только через публичные интерфейсы, которые они реализуют.
  3. Вы не знаете, что вы хотите сказать: "Cast fail". Это было бы неправдоподобно, так как свойство NewItems уже имеет тип IList. Приведение к IList преуспеет тривиально.
  4. Это является истинным, что вы не можете отличить 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, никакое количество кастингов не изменится, что 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 не будет работать.

Но это все проблемы, характерные для остальной части кода. Вы не указали это, поэтому я могу лучше всего объяснить все способы, по которым вы, похоже, неправильно понимаете, как это событие и его поддерживающие типы работают.

+0

Спасибо за ответ, ваш фрагмент идеален. Я вижу, что я думал о NewItems как методе вместо списка. В интересах исправления моего недоразумения, почему ObservableCollection реализует IEnumerable (разрешая метод расширения .ElementAt (index)), все же args реализует IList (не разрешая ElementAt). Я думаю, что это может быть источником моей путаницы. – NWoodsman

+0

'INotifyCollectionChanged' не является общим; он должен работать с любой коллекцией, включая не общие сценарии. Таким образом, общий метод 'ElementAt (int)' не может быть использован там. Обратите внимание, что, хотя вы можете вызывать 'ElementAt (int)' на экземпляре 'ObservableCollection ', вам не нужно, потому что вы можете напрямую индексировать объект ObservableCollection ', например. 'myObservableCollection [17];' для получения элемента в индексе 17. Вы должны предпочесть прямую индексацию использования методов расширения. –

Смежные вопросы