Qual è l'uso di ObservableCollection in .net?


227

Qual è l'uso di ObservableCollection in .net?


1
@ alpha-mouse: puoi fornire qualche informazione in più sul problema che stai cercando di risolvere? Questo aiuterà le persone a darti esempi pertinenti.
Jazza,

@Jazza: ho appena cambiato i tag della domanda =) Non sono la domanda di santosh
alpha-mouse

3
@TheMuffinMan vero, eppure preferisco il modo in cui le cose vengono spiegate su StackOverflow rispetto al modo troppo rigido e formale di MSDN di spiegare le proprie creazioni.
Sizons,

Risposte:


224

ObservableCollection è una raccolta che consente al codice esterno alla raccolta di sapere quando si verificano modifiche alla raccolta (aggiungi, sposta, rimuovi). È ampiamente utilizzato in WPF e Silverlight ma il suo utilizzo non è limitato a questo. Il codice può aggiungere gestori di eventi per vedere quando la raccolta è cambiata e quindi reagire attraverso il gestore di eventi per eseguire ulteriori elaborazioni. Questo potrebbe cambiare un'interfaccia utente o eseguire qualche altra operazione.

Il codice seguente non fa davvero nulla, ma dimostra come assoceresti un gestore in una classe e quindi usi gli arg dell'evento per reagire in qualche modo alle modifiche. WPF ha già molte operazioni come l'aggiornamento dell'interfaccia utente integrata in modo da poterle ottenere gratuitamente quando si utilizza 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
        }
    }
}

21
e.NewItemse e.OldsItemspuò essere nullo a seconda dell'azione. Potrebbe lanciare NullReferenceException.
dovid

7
sidenote: quando Action è Move, l'elemento spostato apparirà in NewItems e OldItems
bohdan_trotsenko

Grazie per questo:> WPF ha già molte operazioni come l'aggiornamento dell'interfaccia utente integrata in modo da poterle ottenere gratuitamente quando si utilizza ObservableCollections
SlowLearner

157

Un ObservableCollectionfunziona essenzialmente come una raccolta regolare, tranne per il fatto che implementa le interfacce:

Pertanto è molto utile quando si desidera sapere quando la raccolta è stata modificata. Viene attivato un evento che indica all'utente quali voci sono state aggiunte / rimosse o spostate.

Ancora più importante, sono molto utili quando si utilizza la banca dati su un modulo.


54

Da Pro C # 5.0 e .NET 4.5 Framework

La ObservableCollection<T>classe è molto utile in quanto ha la capacità di informare oggetti esterni quando i suoi contenuti sono cambiati in qualche modo (come puoi immaginare, lavorare con ReadOnlyObservableCollection<T>è molto simile, ma di sola lettura). In molti modi, lavorare con il ObservableCollection<T>è identico a lavorare con List<T>, dato che entrambe queste classi implementano le stesse interfacce di base. Ciò che rende ObservableCollection<T>unica la classe è che questa classe supporta un evento denominato CollectionChanged. Questo evento si attiva ogni volta che viene inserito un nuovo elemento, viene rimosso (o trasferito) un elemento corrente o se viene modificata l'intera raccolta. Come ogni evento, CollectionChanged è definito in termini di delegato, che in questo caso lo è NotifyCollectionChangedEventHandler. Questo delegato può chiamare qualsiasi metodo che accetta un oggetto come primo parametro e aNotifyCollectionChangedEventArgscome il secondo. Considera il seguente metodo Main (), che popola una raccolta osservabile contenente oggetti Person e collega l' CollectionChangedevento:

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());
            }
        }
   }
}

Il NotifyCollectionChangedEventArgsparametro in entrata definisce due proprietà importanti OldItemse NewItems, che forniranno un elenco di elementi che erano attualmente nella raccolta prima dell'evento generato, e i nuovi elementi coinvolti nella modifica. Tuttavia, vorrai esaminare questi elenchi solo nelle circostanze corrette. Ricorda che l'evento CollectionChanged può attivarsi quando gli elementi vengono aggiunti, rimossi, riposizionati o ripristinati. Per scoprire quale di queste azioni ha attivato l'evento, è possibile utilizzare la proprietà Action di NotifyCollectionChangedEventArgs. La proprietà Action può essere testata con uno dei seguenti membri diNotifyCollectionChangedAction dell'enumerazione:

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

Membri di System.Collections.ObjectModel


1
l'evento people_CollectionChanged verrà attivato se cambio il nome di una persona nella raccolta (senza alterare la raccolta stessa?)
BKSpurgeon

25

Spiegazione senza codice

Per coloro che desiderano una risposta senza alcun codice (boom-tish) alzerò la mano:

Raccolte normali - Nessuna notifica

Ogni tanto vado a New York e mia moglie mi chiede di comprare cose. Quindi porto con me una lista della spesa. L'elenco contiene molte cose come:

  1. Borsa Louis Vuitton ($ 5000)
  2. Profumo di maestà imperiale di Clive Christian ($ 215.000)
  3. Occhiali da sole Gucci ($ 2000)

ahahah beh non sto comprando quella roba. Quindi li cancello e li rimuovo dalla lista e aggiungo invece:

  1. 12 dozzine palline da golf Titleist.
  2. Palla da bowling da 12 libbre.

Quindi di solito torno a casa senza la merce e non è mai contenta. Il fatto è che non sa cosa tolgo dall'elenco e cosa aggiungo; non riceve notifiche.

ObservableCollection: notifiche quando vengono apportate modifiche

Ora, ogni volta che rimuovo qualcosa dall'elenco: riceve una notifica sul suo telefono (ad esempio sms / email ecc.)!

La collezione osservabile funziona allo stesso modo. Se aggiungi o rimuovi qualcosa da o verso di esso: qualcuno viene avvisato. E quando vengono avvisati, allora ti chiamano e ti sentirai pieno. Naturalmente le conseguenze sono personalizzabili tramite il gestore eventi.

Questo riassume tutto!


7

Uno degli usi più importanti è che puoi associare i componenti dell'interfaccia utente a uno e risponderanno in modo appropriato se i contenuti della raccolta cambiano. Ad esempio, se si associa una risorsa di ListView a una, il contenuto di ListView si aggiornerà automaticamente se si modifica la raccolta.

EDIT: Ecco un po 'di codice di esempio da MSDN: http://msdn.microsoft.com/en-us/library/ms748365.aspx

In C #, agganciare ListBox alla raccolta potrebbe essere facile come

listBox.ItemsSource = NameListData;

tuttavia, se non hai collegato l'elenco come risorsa statica e definito NameItemTemplate, potresti voler sostituire ToString () di PersonName. Per esempio:

public override ToString()
{
    return string.Format("{0} {1}", this.FirstName, this.LastName);
}

6

è una raccolta che viene utilizzata per comunicare principalmente all'interfaccia utente di modifiche nella raccolta, supporta la notifica automatica.

Utilizzato principalmente in WPF,

Supponiamo che tu abbia un'interfaccia utente con una casella di riepilogo e un pulsante Aggiungi e quando fai clic su di esso un oggetto di tipo supponi che una persona venga aggiunta alla raccolta obseravabl e tu associ questa raccolta a ItemSource of Listbox, quindi non appena hai aggiunto un nuovo elemento nella raccolta, Listbox si aggiornerà automaticamente e aggiungerà un altro elemento al suo interno.


davvero questo succede ?? : O
Re

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();
}

puoi spiegare perché FooObservableCollection ha implementato la raccolta? E perché hai inserito InsertItem?
Arie,

@Arie: onestamente, 8 anni dopo non ricordo, quindi non ne ho idea. Da quello che vedo nei documenti non è necessario nulla di tutto ciò, tutto dovrebbe uscire fuori dagli schemi.
abatishchev,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.