wpf Observable 集合替换项目

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6873533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 23:00:32  来源:igfitidea点击:

Observable Collection replace item

wpfbindingreplaceobservablecollection

提问by thewayman

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 item and reflect that on my bound components.

我有一个ObservableCollection,我可以从集合中添加和删除项目。但我无法替换集合中的现有项目。有一种方法可以替换一个项目并将其反映在我绑定的组件上。

System.Collections.Specialized.NotifyCollectionChangedAction.Replace

Can anyone please show me how to accomplish this?

谁能告诉我如何做到这一点?

回答by SLaks

collection[someIndex] = newItem;

回答by Mikhail Tumashenko

Updated: Indexer uses overridden SetItem and notifies about changes.

更新:索引器使用覆盖的 SetItem 并通知更改。

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 ObservableCollectionimplementation.

只是为了澄清:ObservableCollection<T>使用来自其基Collection<T>类的索引器,它又是 的包装器List<T>,它是T.的简单数组的包装器。在ObservableCollection实现中没有覆盖索引器方法。

So when you use indexer to replace an item in ObservableCollectionit invokes the following code from Collectionclass:

因此,当您使用索引器替换ObservableCollection 中的项目时,它会调用Collection类中的以下代码:

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 Listclass:

它只是检查边界并调用使用底层List类索引器的 SetItem :

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

During assignment there is no call to the CollectionChangedevent, because underlying collections know nothing of it.

在分配期间,不会调用该CollectionChanged事件,因为底层集合对此一无所知。

But when you use SetItemmethod, it is called from ObservableCollection class:

但是当你使用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);
    }

After assignment it calls OnCollectionChangedmethod, which fires CollectionChangedevent with NotifyCollectionChangedAction.Replaceaction parameter.

分配后它调用OnCollectionChanged方法,该方法CollectionChanged使用NotifyCollectionChangedAction.Replace动作参数触发事件。

    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 Replacemethod that calls base.SetItem()worth a try.

总结:继承自 ObservableCollection 的自定义类和Replace调用方法的想法base.SetItem()值得一试。