可观察集合替换项目

发布于 2024-11-27 05:53:57 字数 205 浏览 1 评论 0原文

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

System.Collections.Specialized.NotifyCollectionChangedAction.Replace

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

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.

System.Collections.Specialized.NotifyCollectionChangedAction.Replace

Can anyone please show me how to accomplish this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞别 2024-12-04 05:53:58

替换可观察集合中的项目的简单扩展方法:

public static void ReplaceItem<T>(this ObservableCollection<T> items, Func<T, bool> predicate, T newItem)
{
    for (int i = 0; i < items.Count; i++)
    {
        if (predicate(items[i]))
        {
            items[i] = newItem;
            break;
        }
    }
}

Simple extension method for replace item in observable collection:

public static void ReplaceItem<T>(this ObservableCollection<T> items, Func<T, bool> predicate, T newItem)
{
    for (int i = 0; i < items.Count; i++)
    {
        if (predicate(items[i]))
        {
            items[i] = newItem;
            break;
        }
    }
}
深海里的那抹蓝 2024-12-04 05:53:57
collection[someIndex] = newItem;
collection[someIndex] = newItem;
梦回旧景 2024-12-04 05:53:57

更新:索引器使用重写的 SetItem 并通知更改。

我认为有关使用索引器的答案可能错误,因为问题是关于替换和通知

只是澄清一下:ObservableCollection 使用其基 Collection 类中的索引器,该类又是 List的包装器;,它是T简单数组的包装。并且 ObservableCollection 实施。

因此,当您使用索引器替换 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);
        }

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

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 的自定义类和调用 base.SetItem()Replace 方法的想法值得一试。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文