2012-05-13 17 views
11

Mam aplikację WPF, która używa powiązań danych MVVM. Dodaję elementy do ObservableCollection<...> i całkiem sporo z nich.Czy mogę w jakiś sposób tymczasowo wyłączyć zmiany wiązania danych WPF?

Teraz zastanawiam się, czy za każdym razem, gdy dodaję jeden do kolekcji, czy natychmiast wywołuje to zdarzenie i powoduje niepotrzebne obciążenie? Jeśli tak, czy mogę w jakiś sposób tymczasowo wyłączyć powiadomienia o zdarzeniach i ręcznie uruchomić je raz na końcu mojego kodu tak, że jeśli dodaję 10k elementów, zostanie ono wyrzucone tylko raz, a nie 10k razy?

Aktualizacja: próbowałem mając tę ​​klasę:

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) { } 
    } 
} 

otrzymuję ten błąd teraz:

Dodatkowe informacje: Zakres działania nie są obsługiwane.

Błąd przychodzi tutaj:

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

Odpowiedz

10

Bardzo szybki i prosty sposób jest do podklasy ObservableCollection i zawiesić informację, kiedy AddRange jest wywoływany. Aby uzyskać wyjaśnienia, patrz: following blog post.

8

Jest to rodzaj „Sztuczki” sposób, ale dość dokładne, moim zdaniem, aby to osiągnąć. Należy napisać własnoręcznie ObservableCollection i zaimplementować obsługę AddRange.

W ten sposób można dodać wszystkie elementy 10k do jakiejś kolekcji „posiadacz” i potem jeden raz skończyłeś używać AddRange z swójObservableColleciton to zrobić.

Więcej na ten temat można znaleźć pod tym linkiem:

ObservableCollection Doesn't support AddRange method....

czy ten też

AddRange and ObservableCollection

+1

Interesujące. Zastanawiam się, dlaczego to nie jest częścią "ObservableCollection". – Tower

+0

@rFactor: honeslty, nie mam pojęcia. Byłoby bardzo miło mieć to jak wbudowane, ale ... może być, że Eric Lippert czasami mówi: ponieważ żaden nie zaimplementował ... – Tigran

+0

Nie jestem w stanie ich zmusić do pracy, dostaję: 'Dodatkowe informacje : Konstruktor obsługuje tylko akcję "Resetuj".'gdy kod wywołuje' OnCollectionChanged (new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add)); '. – Tower

6

To rozszerzenie ObservableCollection rozwiązuje problem z łatwością.

Ujawnia publiczną właściwość SupressNotification, aby umożliwić użytkownikowi kontrolowanie, czy powiadomienie CollectionChanged zostanie wyłączone.

Nie oferuje wstawiania/usuwania zakresów, ale jeśli powiadomienie CollectionChanged jest wyłączone, konieczność wykonywania operacji na zakresie w kolekcji zmniejsza się w większości przypadków.

Ta implementacja zastępuje wszystkie odrzucone powiadomienia powiadomieniem o resetowaniu. Jest to logicznie uzasadnione. Gdy użytkownik anuluje powiadomienie, dokonaj zbiorczych zmian, a następnie włącz je ponownie, należy wysłać powiadomienie o ponownym wysłaniu.

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

Nice Class, podoba mi się soltution, że wystrzeliwujesz wydarzenie po ponownym ustawieniu go na true. – Tobias

Powiązane problemy