可观察集合替换项目

37

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

System.Collections.Specialized.NotifyCollectionChangedAction.Replace

有人能否请示我如何完成这个任务?


可能是一个重复的问题:如何更新ObservableCollection类中的单个项目? - KyleMit
3个回答

75
collection[someIndex] = newItem;

我通过实现以下类来实现这个功能: public class MyObservableCollection<T> : ObservableCollection<T> {public MyObservableCollection() { } public MyObservableCollection(List collection) { MyObservableCollection mb = new MyObservableCollection(); for (int x = 0; x < collection.Count; x++) this.Add(collection[x]); } public void Replace(int index, T item) { base.SetItem(index, item); }} - Taufiq Abdur Rahman
6
不需要创建自己的类,只需编写collection[someIndex] = newItem - SLaks
当我尝试这个答案时,它并不起作用。这个答案确实有效:https://dev59.com/Xmw15IYBdhLWcg3wLIs2 。这是否与对象引用的方式有关? - Chucky
1
使用索引替换项目时,我的UI没有更新。 - Chucky

6

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

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

只是为了澄清:ObservableCollection<T>使用其基类Collection<T>类的索引器,而这个类又是List<T>的包装器,而后者是简单的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);
        }

它只是检查边界并调用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方法,该方法将使用NotifyCollectionChangedAction.Replace操作参数触发CollectionChanged事件。

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

作为结论:从ObservableCollection继承自定义类并调用base.SetItem()的Replace方法是值得一试的想法。

3
[]操作符使用ObservableCollection中被重载的SetItem方法。 - lilo.jacob
感谢澄清。 - Mikhail Tumashenko

0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接