2012-05-13 114 views
11

我有一個使用MVVM數據綁定的WPF應用程序。我正在將項目添加到ObservableCollection<...>,其中很多都是。我可以以某種方式暫時禁用WPF數據綁定更改嗎?

現在我想知道,每次我添加一個集合的時候,它立刻觸發事件而造成不必要的開銷?如果是這樣,我可以以某種方式暫時禁用事件通知,並在我的代碼結束時手動觸發一次,這樣如果我添加10k項目,它只會觸發一次,而不是10k次?

更新:我想有這個類:

using System; 
using System.Linq; 
using System.Collections.Specialized; 
using System.Collections.Generic; 

namespace MyProject 
{ 

    /// <summary> 
    /// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    public class ObservableCollection<T> : System.Collections.ObjectModel.ObservableCollection<T> 
    { 

     /// <summary> 
     /// Adds the elements of the specified collection to the end of the ObservableCollection(Of T). 
     /// </summary> 
     public void AddRange(IEnumerable<T> collection) 
     { 
      foreach (var i in collection) Items.Add(i); 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection.ToList())); 
     } 

     /// <summary> 
     /// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T). 
     /// </summary> 
     public void RemoveRange(IEnumerable<T> collection) 
     { 
      foreach (var i in collection) Items.Remove(i); 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, collection.ToList())); 
     } 

     /// <summary> 
     /// Clears the current collection and replaces it with the specified item. 
     /// </summary> 
     public void Replace(T item) 
     { 
      ReplaceRange(new T[] { item }); 
     } 
     /// <summary> 
     /// Clears the current collection and replaces it with the specified collection. 
     /// </summary> 
     public void ReplaceRange(IEnumerable<T> collection) 
     { 
      List<T> old = new List<T>(Items); 
      Items.Clear(); 
      foreach (var i in collection) Items.Add(i); 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, collection.ToList())); 
     } 

     /// <summary> 
     /// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class. 
     /// </summary> 
     public ObservableCollection() : base() { } 

     /// <summary> 
     /// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection. 
     /// </summary> 
     /// <param name="collection">collection: The collection from which the elements are copied.</param> 
     /// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception> 
     public ObservableCollection(IEnumerable<T> collection) : base(collection) { } 
    } 
} 

我得到現在這個錯誤:

其他信息:範圍的行動不支持。

錯誤來這裏:

OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection.ToList())); 

回答

10

一個非常快速簡便的方法是繼承的ObservableCollection並暫停通知時AddRange被調用。請參閱following blog post以進行說明。

8

有一種「狡猾」的方式,但相當準確的,在我看來,實現這一目標。 是寫你自己ObservableCollection和實施AddRange處理。

這樣您可以將所有10K的元素加入到一些「持有人集」之後,你完成了一個時間,使用的AddRangeObservableColleciton做到這一點。

更多關於這一點,你可以找到這個鏈接:

ObservableCollection Doesn't support AddRange method....

或這一個了

AddRange and ObservableCollection

+1

有趣。我想知道爲什麼這不是'ObservableCollection'的一部分。 – Tower

+0

@rFactor:honeslty,不知道。這將是非常不錯的,像內置的,但是......可能是,艾克埃裏克利珀有時說:因爲沒有它實現... – Tigran

+0

我不能讓他們的工作,我得到:'其他信息:構造器僅支持「重置」操作。'當代碼調用OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));'。 – Tower

6

這個擴展的ObservableCollection容易解決的問題。

它公開了一個公共SupressNotification屬性,以允許用戶控制何時CollectionChanged通知將被抑制。

它不提供範圍的插入/缺失,但如果CollectionChanged告知被抑制,需要做的收集範圍操作在大多數情況下,減少。

此實現替代了重置通知所有抑制通知。這在邏輯上是合理的。當用戶禁止通知,進行批量更改然後重新啓用它時,它應該適合發送一個重發通知。

public class ObservableCollectionEx<T> : ObservableCollection<T> 
{ 
    private bool _notificationSupressed = false; 
    private bool _supressNotification = false; 
    public bool SupressNotification 
    { 
     get 
     { 
      return _supressNotification; 
     } 
     set 
     { 
      _supressNotification = value; 
      if (_supressNotification == false && _notificationSupressed) 
      { 
       this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
       _notificationSupressed = false; 
      } 
     } 
    } 

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    { 
     if (SupressNotification) 
     { 
      _notificationSupressed = true; 
      return; 
     } 
     base.OnCollectionChanged(e); 
    } 
} 
+0

好的類,我喜歡你重新設置爲true後觸發事件的解決方案。 – Tobias

相關問題