簡體   English   中英

哪個.Net集合可一次添加多個對象並得到通知?

[英]Which .Net collection for adding multiple objects at once and getting notified?

正在考慮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

似乎INotifyCollectionChanged接口允許在添加多個項目時進行更新,因此我不確定為什么ObservableCollection<T>沒有AddRange 您可以為AddRange創建擴展方法,但這將為添加的每個項目導致一個事件。 如果那是不可接受的,那么您應該能夠從ObservableCollection<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);
    }
}

好吧,這個想法與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);
        }

    }
}

System.Collections.ObjectModel.Collection<T>不僅是一個不錯的選擇,而且在幫助文檔中,有一個示例如何覆蓋其各種受保護的方法以獲得通知。 (向下滾動到示例2。)

如果您使用上述任何一種發送添加范圍命令並將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));
    }

我已經多次看到這種問題,而且我想知道為什么連微軟都在其他地方已經推廣了更好的collection的地方推廣ObservableCollection。

BindingList<T>

這使您可以關閉通知並執行批量操作,然后打開通知。

如果要從某種集合中繼承,最好從System.Collections.ObjectModel.Collection繼承,因為它提供了用於重寫的虛擬方法。 如果走那條路線,您將不得不將方法從List中刪除。

我不知道任何提供此功能的內置集合,但我歡迎對此進行糾正:)

類似於CollectionView模式的另一個解決方案:

public class DeferableObservableCollection<T> : ObservableCollection<T>
{
    private int deferLevel;

    private class DeferHelper<T> : IDisposable
    {
        private DeferableObservableCollection<T> owningCollection;
        public DeferHelper(DeferableObservableCollection<T> owningCollection)
        {
            this.owningCollection = owningCollection;
        }

        public void Dispose()
        {
            owningCollection.EndDefer();
        }
    }

    private void EndDefer()
    {
        if (--deferLevel <= 0)
        {
            deferLevel = 0;
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }
    }

    public IDisposable DeferNotifications()
    {
        deferLevel++;
        return new DeferHelper<T>(this);
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (deferLevel == 0) // Not in a defer just send events as normally
        {
            base.OnCollectionChanged(e);
        } // Else notify on EndDefer
    }
}

從List <T>繼承並重寫Add()和AddRange()方法引發事件?

看看C#和VB中具有AddRange,RemoveRange和Replace range方法的Observable集合

在VB中:INotifyCollectionChanging實現。

為了快速添加,您可以使用:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM