Observable Collection replace item

前端 未结 2 935
闹比i
闹比i 2021-02-11 17:05

I have a ObservableCollection, I can add and remove item from the collection. But I can\'t replace an existing item in the collection. There is a way to replace an

相关标签:
2条回答
  • 2021-02-11 17:48
    collection[someIndex] = newItem;
    
    0 讨论(0)
  • 2021-02-11 17:50

    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.

    0 讨论(0)
提交回复
热议问题