Jakie jest zastosowanie ObservableCollection w .net?

227

Jakie jest zastosowanie ObservableCollection w .net?

Santosh Singh
źródło
1
@ alpha-mouse: Czy możesz podać nieco więcej informacji na temat problemu, który próbujesz rozwiązać? Pomoże to ludziom podać odpowiednie przykłady.
Jazza
@Jazza: Właśnie zmieniłem tagi pytania =) Nie jestem pytaniem Santosha
mysz alfa
3
@TheMuffinMan to prawda, ale wolę sposób, w jaki rzeczy są wyjaśniane przy przepełnieniu stosu w porównaniu do zbyt sztywnego MSDN niż formalny sposób wyjaśniania własnych dzieł.
Sizons,

Odpowiedzi:

224

ObservableCollection to kolekcja, która pozwala kodowi spoza kolekcji być świadomym tego, kiedy nastąpią zmiany w kolekcji (dodawanie, przenoszenie, usuwanie). Jest intensywnie używany w WPF i Silverlight, ale jego użycie nie ogranicza się do tego. Kod może dodawać procedury obsługi zdarzeń, aby zobaczyć, kiedy zmieniła się kolekcja, a następnie reagować za pośrednictwem procedury obsługi zdarzeń, aby wykonać dodatkowe przetwarzanie. Może to być zmiana interfejsu użytkownika lub wykonanie innej operacji.

Poniższy kod tak naprawdę nic nie robi, ale pokazuje, jak dołączyć moduł obsługi do klasy, a następnie użyć argumentów zdarzeń, aby w jakiś sposób zareagować na zmiany. WPF ma już wiele operacji, takich jak odświeżanie wbudowanego interfejsu użytkownika, dzięki czemu można je uzyskać bezpłatnie podczas korzystania z ObservableCollections

class Handler
{
    private ObservableCollection<string> collection;

    public Handler()
    {
        collection = new ObservableCollection<string>();
        collection.CollectionChanged += HandleChange;
    }

    private void HandleChange(object sender, NotifyCollectionChangedEventArgs e)
    {
        foreach (var x in e.NewItems)
        {
            // do something
        }

        foreach (var y in e.OldItems)
        {
            //do something
        }
        if (e.Action == NotifyCollectionChangedAction.Move)
        {
            //do something
        }
    }
}
Craig Suchanec
źródło
21
e.NewItemsi e.OldsItemsmoże być zerowy w zależności od akcji. Może rzucić NullReferenceException.
dovid
7
sidenote: kiedy Action is Move, przeniesiony element pojawi się zarówno w NewItems, jak i OldItems
bohdan_trotsenko
Dziękujemy za to:> WPF ma już wiele operacji, takich jak odświeżanie wbudowanego interfejsu użytkownika, więc dostajesz je za darmo podczas korzystania z ObservableCollections
SlowLearner
157

ObservableCollectionDziała w zasadzie jak zwykły kolekcji poza tym, że implementuje interfejsy:

Jako taki jest bardzo przydatny, gdy chcesz wiedzieć, kiedy zmieniła się kolekcja. Wyzwalane jest zdarzenie, które poinformuje użytkownika, które wpisy zostały dodane / usunięte lub przeniesione.

Co ważniejsze, są one bardzo przydatne podczas korzystania z wiązania danych w formularzu.

Liz
źródło
54

Od Pro C # 5.0 i .NET 4.5 Framework

ObservableCollection<T>Klasa jest bardzo przydatna tym, że posiada zdolność do informowania zewnętrznych obiektów, gdy jej zawartość zostały zmienione w jakiś sposób (jak można się domyślać, praca z ReadOnlyObservableCollection<T>jest bardzo podobny, ale tylko do odczytu w naturze). Pod wieloma względami praca z nią ObservableCollection<T>jest identyczna z pracą z tym List<T>, że obie te klasy implementują te same podstawowe interfejsy. Tym, co czyni tę ObservableCollection<T>klasę wyjątkową, jest to, że ta klasa obsługuje zdarzenie o nazwie CollectionChanged. To zdarzenie będzie uruchamiane za każdym razem, gdy zostanie wstawiony nowy element, bieżący element zostanie usunięty (lub przeniesiony) lub jeśli cała kolekcja zostanie zmodyfikowana. Jak każde zdarzenie, CollectionChanged jest zdefiniowane w kategoriach delegata, którym w tym przypadku jest NotifyCollectionChangedEventHandler. Ten delegat może wywołać dowolną metodę, która przyjmuje obiekt jako pierwszy parametr, orazNotifyCollectionChangedEventArgsjako drugi. Rozważ następującą metodę Main (), która zapełnia obserwowalną kolekcję zawierającą obiekty Person i łączy CollectionChangedzdarzenie:

class Program
{
   static void Main(string[] args)
   {
     // Make a collection to observe and add a few Person objects.
     ObservableCollection<Person> people = new ObservableCollection<Person>()
     {
        new Person{ FirstName = "Peter", LastName = "Murphy", Age = 52 },
        new Person{ FirstName = "Kevin", LastName = "Key", Age = 48 },
     };
     // Wire up the CollectionChanged event.
     people.CollectionChanged += people_CollectionChanged;
     // Now add a new item.
     people.Add(new Person("Fred", "Smith", 32));

     // Remove an item.
     people.RemoveAt(0);

     Console.ReadLine();
   }
   static void people_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
   {
       // What was the action that caused the event?
        Console.WriteLine("Action for this event: {0}", e.Action);

        // They removed something. 
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
        {
            Console.WriteLine("Here are the OLD items:");
            foreach (Person p in e.OldItems)
            {
                Console.WriteLine(p.ToString());
            }
            Console.WriteLine();
        }

        // They added something. 
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            // Now show the NEW items that were inserted.
            Console.WriteLine("Here are the NEW items:");
            foreach (Person p in e.NewItems)
            {
                Console.WriteLine(p.ToString());
            }
        }
   }
}

Przychodzące NotifyCollectionChangedEventArgsparametr definiuje dwie ważne właściwości, OldItemsa NewItems, co daje listę elementów, które są obecnie w zbiorach przed wydarzeniem zwolniony, a nowe elementy, które były zaangażowane w zmiany. Będziesz jednak chciał sprawdzić te listy tylko w odpowiednich okolicznościach. Przypomnij sobie, że zdarzenie CollectionChanged może zostać uruchomione, gdy elementy zostaną dodane, usunięte, przeniesione lub zresetowane. Aby dowiedzieć się, które z tych działań wywołały zdarzenie, możesz użyć właściwości Action NotifyCollectionChangedEventArgs. Właściwość Action można przetestować pod kątem dowolnego z następujących elementów NotifyCollectionChangedActionwyliczenia:

public enum NotifyCollectionChangedAction
{
Add = 0,
Remove = 1,
Replace = 2,
Move = 3,
Reset = 4,
}

Członkowie System.Collections.ObjectModel

Powiedział Roohullah Allem
źródło
1
czy zdarzenie people_CollectionChanged zostanie uruchomione, jeśli zmienię nazwisko osoby w kolekcji (bez zmiany samej kolekcji?)
BKSpurgeon
25

Wyjaśnienie bez kodu

Dla tych, którzy chcą odpowiedzi bez żadnego kodu (boom-tish) podniosę rękę:

Normalne kolekcje - brak powiadomień

Co jakiś czas jeżdżę do Nowego Jorku, a moja żona prosi mnie o kupienie rzeczy. Więc biorę ze sobą listę zakupów. Lista zawiera wiele rzeczy, takich jak:

  1. Torebka Louis Vuitton (5000 $)
  2. Perfumy Imperial Majesty Clive'a Christiana (215 000 $)
  3. Okulary przeciwsłoneczne Gucci (2000 USD)

hahaha cóż, nie kupuję tych rzeczy. Skreślam je i usuwam z listy, a zamiast tego dodaje:

  1. 12 tuzinów piłek golfowych Titleist.
  2. Kula do kręgli 12 funtów.

Więc zwykle wracam do domu bez towarów, a ona nigdy nie jest zadowolona. Chodzi o to, że nie wie o tym, co usuwam z listy i co dodam do niej; nie otrzymuje powiadomień.

The ObservableCollection - powiadomienia o dokonanych zmianach

Teraz, ilekroć coś usuwam z listy: dostaje powiadomienie na swój telefon (np. Sms / email itp.)!

Obserwowalna kolekcja działa w ten sam sposób. Jeśli dodasz lub usuniesz coś do niego lub z niego: ktoś zostanie powiadomiony. A kiedy zostaną powiadomieni, to zadzwonią do ciebie, a dostaniesz pełne ucho. Oczywiście konsekwencje można dostosować za pomocą modułu obsługi zdarzeń.

To wszystko podsumowuje!

BKSpurgeon
źródło
7

Jednym z największych zastosowań jest to, że możesz powiązać komponenty interfejsu użytkownika z jednym i będą odpowiednio reagować, jeśli zawartość kolekcji się zmieni. Na przykład, jeśli powiążesz element Items ListView z jednym, zawartość ListView zostanie automatycznie zaktualizowana po zmodyfikowaniu kolekcji.

EDYCJA: Oto przykładowy kod z MSDN: http://msdn.microsoft.com/en-us/library/ms748365.aspx

W języku C # podpięcie ListBox do kolekcji może być tak proste, jak

listBox.ItemsSource = NameListData;

chociaż jeśli nie podłączyłeś listy jako zasobu statycznego i nie zdefiniowałeś NameItemTemplate, możesz zastąpić ToString () PersonName. Na przykład:

public override ToString()
{
    return string.Format("{0} {1}", this.FirstName, this.LastName);
}
Sean U
źródło
6

jest to kolekcja służąca do powiadamiania głównie interfejsu użytkownika o zmianie kolekcji, obsługuje automatyczne powiadamianie.

Używany głównie w WPF,

Załóżmy, że załóżmy, że masz interfejs użytkownika z listą i przyciskiem dodawania, a po kliknięciu tego przycisku obiekt typu przypuszcza, że ​​osoba zostanie dodana do zbioru obseravablecollection, a ty połączysz tę kolekcję z ItemSource of Listbox, tak szybko jak tylko dodasz nowy element w kolekcji, Listbox zaktualizuje się i doda jeszcze jeden element.

TalentTuner
źródło
naprawdę to się dzieje ?? : O
Kings
5
class FooObservableCollection : ObservableCollection<Foo>
{
    protected override void InsertItem(int index, Foo item)
    {
        base.Add(index, Foo);

        if (this.CollectionChanged != null)
            this.CollectionChanged(this, new NotifyCollectionChangedEventArgs (NotifyCollectionChangedAction.Add, item, index);
    }
}

var collection = new FooObservableCollection();
collection.CollectionChanged += CollectionChanged;

collection.Add(new Foo());

void CollectionChanged (object sender, NotifyCollectionChangedEventArgs e)
{
    Foo newItem = e.NewItems.OfType<Foo>().First();
}
abatishchev
źródło
możesz wyjaśnić, dlaczego kolekcja zaimplementowana przez FooObservableCollection? A dlaczego przeceniłeś InsertItem?
Arie,
@Arie: szczerze mówiąc, 8 lat później nie pamiętam, więc nie mam pojęcia. Z tego, co widzę w dokumentach, nie ma takiej potrzeby, wszystko powinno wyjść z pudełka.
abatishchev