Наблюдаемая коллекция заменяет элемент

У меня есть ObservableCollection, я могу добавить и удалить элемент из коллекции. Но я не могу заменить существующий элемент в коллекции. Существует способ заменить элемент и отразить это на моих связанных компонентах.

System.Collections.Specialized.NotifyCollectionChangedAction.Replace

Может ли кто-нибудь показать мне, как это сделать?

Ответы

Ответ 1

collection[someIndex] = newItem;

Ответ 2

Обновлено: Indexer использует переопределенный SetItem и уведомляет об изменениях.

Я думаю, что ответ об использовании индексатора может быть неправильным, потому что вопрос был о заменять и уведомлять.Дел >

Просто пояснить: ObservableCollection<T> использует indexer из своего базового класса Collection<T>, который, в свою очередь, является оберткой List<T>, которая является оболочкой простого массива T. И нет переопределения для метода индексатора в ObservableCollection реализации.

Поэтому, когда вы используете индекс для замены элемента в ObservableCollection, он вызывает следующий код из класса Коллекция:

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);
        }

Он просто проверяет границы и вызывает SetItem, который использует индексатор базового класса List:

protected virtual void SetItem(int index, T item) {
        items[index] = item;
    }

Во время назначения нет вызова события CollectionChanged, потому что базовые коллекции ничего не знают об этом.

Но когда вы используете метод SetItem, он вызывается из класса ObservableCollection:

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);
    }

После назначения он вызывает метод OnCollectionChanged, который запускает событие CollectionChanged с параметром действия NotifyCollectionChangedAction.Replace.

    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (CollectionChanged != null)
        {
            using (BlockReentrancy())
            {
                CollectionChanged(this, e);
            }
        }
    }

В качестве вывода: идея с пользовательским классом, унаследованным от метода ObservableCollection и Replace, который вызывает base.SetItem(), стоит попробовать.