Observable Collection replace item
Updated: Indexer uses overridden SetItem and notifies about changes.
I think the answer about using indexer may be wrong, because the question was about replace and notify.
Just to clarify: ObservableCollection<T>
uses indexer from its base Collection<T>
class, which in turn is a wrapper of List<T>
, which is a wrapper of simple array of T
. And there's no override for indexer method in ObservableCollection implementation.
So when you use indexer to replace an item in ObservableCollection it invokes the following code from Collection class:
public T this[int index] { get { return items[index]; } set { if( items.IsReadOnly) { ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection); } if (index < 0 || index >= items.Count) { ThrowHelper.ThrowArgumentOutOfRangeException(); } SetItem(index, value); }
It just checks boundaries and calls SetItem that uses indexer of underlying List class:
protected virtual void SetItem(int index, T item) { items[index] = item; }
During assignment there is no call to the CollectionChanged
event, because underlying collections know nothing of it.
But when you use SetItem
method, it is called from ObservableCollection class:
protected override void SetItem(int index, T item) { CheckReentrancy(); T originalItem = this[index]; base.SetItem(index, item); OnPropertyChanged(IndexerName); OnCollectionChanged(NotifyCollectionChangedAction.Replace, originalItem, item, index); }
After assignment it calls OnCollectionChanged
method, which fires CollectionChanged
event with NotifyCollectionChangedAction.Replace
action parameter.
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { if (CollectionChanged != null) { using (BlockReentrancy()) { CollectionChanged(this, e); } } }
As a conclusion: the idea with custom class inherited from ObservableCollection and Replace
method that calls base.SetItem()
worth a try.