哪个.Net集合可一次添加多个对象并获得通知?

时间:2020-03-05 18:51:38  来源:igfitidea点击:

正在考虑使用System.Collections.ObjectModel ObservableCollection <T>类。这个很奇怪,因为

  • 它有一个只需要一项的添加方法。没有AddRange或者等效项。
  • Notification事件参数具有NewItems属性,该属性是一个IList(对象的..不是T)

我在这里的需要是将一批对象添加到集合中,并且侦听器还将批处理作为通知的一部分。我是否缺少ObservableCollection的东西?还有其他符合我要求的课程吗?

更新:不想自己动手做。我必须建立在添加/删除/更改等..很多东西。

相关问题:
https://stackoverflow.com/questions/670577/observablecollection-doesnt-support-addrange-method-so-i-get-notified-for-each

解决方案

回答

从List <T>继承并重写Add()和AddRange()方法引发事件?

回答

如果要从某种集合中继承,最好从System.Collections.ObjectModel.Collection继承,因为它提供了用于重写的虚拟方法。如果走那条路线,我们将不得不使方法脱离List。

我不知道任何提供此功能的内置集合,但我欢迎对此进行纠正:)

回答

看来,INotifyCollectionChanged接口允许在添加多个项目时进行更新,所以我不确定为什么ObservableCollection &lt;T>没有AddRange。我们可以为AddRange创建扩展方法,但这会为添加的每个项目引发一个事件。如果那是不可接受的,我们应该可以从ObservableCollection &lt;T>继承,如下所示:

public class MyObservableCollection<T> : ObservableCollection<T>
{
    // matching constructors ...

    bool isInAddRange = false;

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        // intercept this when it gets called inside the AddRange method.
        if (!isInAddRange) 
            base.OnCollectionChanged(e);
    }

    public void AddRange(IEnumerable<T> items)
    {
         isInAddRange = true;
         foreach (T item in items)
            Add(item);
         isInAddRange = false;

         var e = new NotifyCollectionChangedEventArgs(
             NotifyCollectionChangedAction.Add,
             items.ToList());
         base.OnCollectionChanged(e);
    }
}

回答

扩展方法救援人员!

/// <summary>
    /// Adds all given items to the collection
    /// </summary>
    /// <param name="collection">The collection.</param>
    /// <param name="toAdd">Objects to add.</param>
    public static void AddAll<T>(this IList<T> collection, params T[] toAdd)
    {
        foreach (var o in toAdd)
            collection.Add(o);
    }

回答

System.Collections.ObjectModel.Collection <T>不仅是一个不错的选择,而且在帮助文档中,有一个示例如何覆盖其各种受保护的方法以获取通知。 (向下滚动到示例2. )

回答

好吧,这个想法和fryguybob有点一样,奇怪的是ObservableCollection差不多完成了一半。这个东西的事件args甚至都没有使用Generics ..让我使用IList(就是这样..昨天:)
经过测试的代码段如下...

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace MyNamespace
{
    public class ObservableCollectionWithBatchUpdates<T> : ObservableCollection<T>
    {
        public void AddRange(ICollection<T> obNewItems)
        {
            IList<T> obAddedItems = new List<T>();
            foreach (T obItem in obNewItems)
            {
                Items.Add(obItem);
                obAddedItems.Add(obItem);
            }
            NotifyCollectionChangedEventArgs obEvtArgs = new NotifyCollectionChangedEventArgs(
               NotifyCollectionChangedAction.Add, 
               obAddedItems as System.Collections.IList);
            base.OnCollectionChanged(obEvtArgs);
        }

    }
}

回答

如果我们使用上述任何一种发送添加范围命令并将observablecolletion绑定到listview的实现,则将收到此讨厌的错误。

NotSupportedException
   at System.Windows.Data.ListCollectionView.ValidateCollectionChangedEventArgs(NotifyCollectionChangedEventArgs e)
   at System.Windows.Data.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)

我使用的实现使用Reset事件,该事件在WPF框架周围更均匀地实现:

public void AddRange(IEnumerable<T> collection)
    {
        foreach (var i in collection) Items.Add(i);
        OnPropertyChanged("Count");
        OnPropertyChanged("Item[]");
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

回答

看一下Cand VB中具有AddRange,RemoveRange和Replace range方法的Observable集合。

在VB中:INotifyCollectionChanging实现。

回答

为了快速添加,我们可以使用:

((List<Person>)this.Items).AddRange(NewItems);

回答

我已经多次看到这种问题,而且我想知道为什么连微软都在其他地方已经推广了更好的collection的地方推广ObservableCollection。

BindingList<T>

这使我们可以关闭通知并执行批量操作,然后打开通知。