Observable Collection: impariamo ad utilizzarla

Print Content | More

Premessa: se avete già sviluppato applicazioni Silverlight, quasi sicuramente conoscerete già l’argomento di oggi, quindi potete anche risparmiarvi la lettura di questo post Smile

Se invece avete iniziato da interessarvi a Silverlight da poco grazie a Windows Phone, allora magari potreste non conoscere il tipo Observable Collection. Di cosa si tratta? Molto semplicemente, di una collezione di dati, che si comporta in maniera analoga a List: viene definita infatti come ObservableCollection<Type>, dove Type è il tipo di oggetti che conterrà la collezione. Ne deduciamo che una Observable Collection può contenere solamente oggetti dello stesso tipo.

Esattamente come le collezioni di tipo List, al contrario di un array non siamo obbligati a definirne la capacità in fase di definizione: offre infatti tutta una serie di metodi (come Add, Insert e Remove) per modificarne il contenuto a runtime. In più, permette di fare operazioni di ricerca al suo interno usando query LINQ.

La differenza principale però rispetto al tipo List è che implementa l’interfaccia INotifyPropertyChanged, che permette di notificare in automatico al controllo che è in binding con la collezione quando questa subisce delle modifiche. Questo significa che, ogni qualvolta aggiungiamo o rimuoviamo un elemento, il controllo si aggiorna automaticamente, senza bisogno da parte nostra di rifare il binding.

Proviamo a capire meglio il funzionamento della Observable Collection con un esempio pratico: apriamo il solito Visual Studio e creiamo un progetto di tipo Silverlight for Windows Phone. Nella pagina iniziale (MainPage.xaml) andremo ad inserire un piccolo form per gestire una ipotetica collezione di film, così strutturato:

  • Una textbox, dove inseriremo il titolo di un film.
  • Un pulsante Add, per aggiungere il film.
  • Un pulsante Refresh, per aggiornare la ListBox che è in binding con la collezione.
  • Una ListBox, che mostra i titoli dei film presenti nella collezione.

Ecco lo XAML da inserire nella Grid dal nome ContentGrid per realizzare il form:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBox x:Name="txtTitle" Width="350"></TextBox>
        <Button x:Name="btnAdd" Content="Add" Click="btnAdd_Click"></Button>
    </StackPanel>
    <ListBox x:Name="listItems">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Title}"></TextBlock>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

Ora andiamo a definire la classe Movie, che andrà a rappresentare il nostro film. Dato che ci serve solamente per scopi dimostrativi, definiremo una sola proprietà, il titolo del film. Creiamo perciò una nuova classe (tasto destro sul progetto, Add, New Item, selezioniamo Class e chiamiamola Movie.cs) e definiamola nel modo seguente:

public class Movie
{
    public string Title { get; set; }
}

Ora possiamo iniziare a utilizzarla nell’applicazione vera e propria: posizioniamoci nel code behind (MainPage.xaml.cs) e definiamo una nuova collezione a livello di classe, in modo che sia visibile a tutti i metodi ed eventi che definiremo.

1° esperimento: utilizziamo una collezione di tipo List

Facciamo prima una prova utilizzando una collezione di tipo List tradizionale: ecco il codice sorgente della nostra pagina.

public partial class List : PhoneApplicationPage
{
    private List<Movie> movies;

    public List()
    {
        InitializeComponent();
        movies=new List<Movie>();
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        Movie movie = new Movie
                          {
                              Title = txtTitle.Text
                          };
        movies.Add(movie);
    }

    private void btnRefresh_Click(object sender, RoutedEventArgs e)
    {
        listItems.ItemsSource = null;
        listItems.ItemsSource = movies;
    }
}

Abbiamo definito una nuova collezione di tipo List, che inizializziamo nel momento in cui viene instanziata la pagina (quindi dopo che viene chiamato il metodo InitializeComponent()).

Dopodichè andiamo a gestire gli eventi associati ai due pulsanti presenti nel form:

  • Quando viene premuto il pulsante Add, creiamo una nuova istanza della nostra classe Movie, impostiamo la proprietà Title con il valore inserito nella textbox txtTitle, dopodichè aggiungiamo il nuovo oggetto alla nostra collezione.
  • Quando viene premuto il pulsante Refresh, effettuiamo il binding vero e proprio, associando alla proprietà ItemsSource la nostra collezione. Prima di fare questa operazione, però, forziamo il refresh impostando il binding a null.

Ora possiamo provare la nostra applicazione: premiamo F5 e, una volta avviata, inseriamo del testo nella textbox, dopodichè premiamo il pulsante Add. All’apparenza non succederà niente: per vedere un cambiamento, dobbiamo premere il pulsante Refresh. A questo punto la nostra ListBox si aggiornerà e potremo vedere nell’elenco il titolo del film che abbiamo appena inserito. Possiamo ripetere l’esperimento quante volte vogliamo, il risultato sarà sempre lo stesso: per vedere l’elemento che abbiamo aggiunto nella ListBox dovremo sempre premere il pulsante Refresh.

2° esperimento: utilizziamo una collezione di tipo ObservableCollection

Ora modifichiamo leggermente l’applicazione, così da poter utilizzare una ObservableCollection. Ecco il nuovo codice:

public partial class ObservableCollection : PhoneApplicationPage
{
    private ObservableCollection<Movie> movies;

    public ObservableCollection()
    {
        InitializeComponent();
        movies=new ObservableCollection<Movie>();
        listItems.ItemsSource = movies;
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        Movie movie = new Movie
                          {
                              Title = txtTitle.Text
                          };
        movies.Add(movie);
    }
}

 

Cosa è cambiato? Innanzitutto, abbiamo eliminato il pulsante Refresh: ora il binding viene fatto direttamente in fase di inizializzazione della pagina. E’ rimasto solamente il metodo associato al pulsante Add, che svolge lo stesso compito di prima: aggiungere un nuovo elemento alla collezione.

Ora lanciamo nuovamente l’applicazione e ripetiamo l’esperimento: questa volta, appena premuto il pulsante Add, il titolo appena inserito verrà mostrato nella ListBox, senza alcuna necessità da parte nostra di forzare il refresh. Cool vero? Smile

Lo stesso identico risultato lo avremmo ottenuto se avessimo eliminato un elemento dalla lista, oppure avessimo cambiato l’ordine degli elementi.

Di seguito trovate il link per scaricare il codice sorgente di un piccolo progetto d’esempio, dove, in due diverse pagine, sono implementati gli esempi riportati in questo post: uno che utilizza List e uno che utilizza ObservableCollection.


Windows Phone , Observable Collection , List

3 comments

Related Post

  1. #1 da Matteo Migliore Wednesday October 2010 alle 11:14

    Piccola aggiunta: ObservableCollection implementa anche INotifyCollectionChanged, che permette di interchettare i cambiamenti alla collection.

  2. #2 da Morena Pietraccini Monday February 2011 alle 04:38

    ma secondo te esistono dei limiti sulle observablecollection per cui se si supera un determinato numero di record caricati va in errore?
    grazie

  3. #3 da Matteo Pagani Tuesday February 2011 alle 10:09

    Ciao Morena,
    che io sappia no, anche se puoi incorrere in seri problemi di performance se la tua collezione diventa troppo "numerosa".

    Quanti item contiene indicativamente la tua ObservableCollection? E' in binding con qualche controllo (ad eesmpio, un ListBox?)


(will not be published)
(es: http://www.mysite.com)


  1. #1 da http://qmatteoq.tostring.it/blog/post/i-primi-passi-con-windows-8-e-winrt-listbox-e-collezioni-di-dati

    qmatteoq.tostring.it - I primi passi con Windows 8 e WinRT: Listbox e collezioni di dati