2012-05-13 3 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 요소를 추가 AddRange를 사용할 수 있습니다 ObservableColleciton 그렇게합니다.

이 링크를 찾을 수 있습니다 이것에 더 :

ObservableCollection Doesn't support AddRange method....

거나 너무 이것

AddRange and ObservableCollection

+1

흥미 롭습니다. 이것이 왜 ObservableCollection의 일부가 아닌지 궁금합니다. – Tower

+0

@rFactor : honeslty, 전혀 모르겠습니다. 내장되어있는 것처럼 좋으면 좋겠지 만 ... lke일지도 모릅니다. 에릭 리 퍼트 (Eric Lippert)는 때때로 다음과 같이 말합니다 : 구현하지 않았기 때문에 ... – 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

좋은 수업, 나는 그것을 다시 설정 한 후에 이벤트를 시작하는 해결책을 좋아합니다. – Tobias

관련 문제