MVVM e Windows Phone – La view (3° parte)

Print Content | More

Dopo aver introdotto le basi teoriche del pattern MVVM (nel primo post) e aver realizzato il model e il view model (nel secondo post), siamo pronti per entrare nel “vivo” del pattern, andando a vedere come gestire il collegamento tra la view e il relativo view model. Ci sono diversi approcci per raggiungere il risultato: quello di cui vi parlerò in questo post è tramite il ViewModelLocator.

Il ViewModelLocator

Il ViewModelLocator è una classe che si occupa di “servire” i view model quando richiesti, esponendo una proprietà per ognuno dei view model di cui dispone il progetto. Il ViewModelLocator viene definito come risorsa globale dell’applicazione (all’interno quindi del file App.xaml), dopodichè ogni vista andrà a impostare come DataContext generale il suo specifico view model dichiarato nel ViewModelLocator.

Rispetto ad altri approcci, lo svantaggio del ViewModelLocator è che costituisce una classe in più da mantenere; il vantaggio, però, è che siamo in grado di gestire con molta facilità le dipendenze che un view model può avere (ad esempio, eventuali parametri nel costruttore).

La struttura del ViewModelLocator è molto semplice: dopo aver creato una nuova classe con il nome che preferiamo (va benissimo ViewModelLocator), dobbiamo dichiarare una proprietà pubblica per ognuno dei view model. Riprendendo l’applicazione per leggere un feed reader che stiamo sviluppando, il ViewModelLocator, inizialmente, conterrà solamente un view model (MainViewModel), associato all’unica view disponibile (MainPage.xaml).

public class ViewModelLocator
{
    private MainViewModel _mainViewModel;

    public MainViewModel MainViewModel
    {
        get { return _mainViewModel ?? (_mainViewModel = new MainViewModel()); }
    }
}

Nel momento in cui dovremo aggiungere nuovi view model nell’applicazione (ad esempio, perchè creiamo una vista per leggere il dettaglio di una notizia), dovremo andare a inserire una nuova proprietà.

A questo punto dobbiamo dichiarare il ViewModelLocator come risorsa globale, affinchè tutte le viste possano accedervi direttamente dallo XAML. Per farlo è sufficiente portarci nel file App.xaml e, nella sezione Application.Resources, aggiungere il ViewModelLocator con una chiave univoca.

<Application.Resources>
    <ViewModels:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>

Ovviamente dovrete prima importare il namespace del vostro ViewModelLocator nello XAML per potervi accedere, come nell’esempio seguente:

xmlns:ViewModels="clr-namespace:MVVM_FeedReader.ViewModels

La View

A questo punto possiamo andare a realizzare l’interfaccia grafica della nostra applicazione. Il primo step è collegare il view model alla view: per farlo, andiamo a sfruttare il ViewModelLocator appena definito e la proprietà DataContext. Se avete famigliarità con il binding del mondo XAML, saprete già cosa fa questa proprietà: una volta impostato una classe come DataContext di un controllo, il controllo stesso e tutti i suoi figli (seguendo la struttura ad albero dello XAML) potranno accedere alle proprietà pubblica di quella classe. Ecco perchè andiamo a definire il view model come DataContext dell’intera pagina, in modo che tutti i controlli che inseriremo possano avere accesso alle varie proprietà.

<phone:PhoneApplicationPage.DataContext>
    <Binding Source="{StaticResource ViewModelLocator}" Path="MainViewModel" />
</phone:PhoneApplicationPage.DataContext>

Utilizzando questa dichiarazione andiamo a definire il DataContext utilizzando come sorgente il ViewModelLocator e come valore dell’attributo Path il view model corrispondente alla view che stiamo realizzando.

A questo punto il gioco è fatto: possiamo realizzare la UI inserendo tutti i controlli che vogliamo e, tramite il binding, utilizzare le proprietà definite nel nostro view model per mostrare i dati.

Ad esempio, dato il view model che abbiamo visto nel post precedente, ecco come creare una ListBox che venga popolata dalla proprietà FeedItems (se ricordate si trattava di una collezione di tipo ObservableCollection<FeedItem>).

<ListBox ItemsSource="{Binding Path=FeedItems}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Path=Title}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Come vedete, non è più necessario dal code behind valorizzare la proprietà ItemsSource tramite un riferimento alla ListBox, ma facciamo tutto direttamente nello XAML, lasciando il code behind “intatto”.

Qualche scenario avanzato

Nel prossimo post vedremo come gestire gli eventi e l’interazione con l’utente. Nel frattempo, potete scaricare il progetto di esempio utilizzato fino ad ora: nei prossimi post lo espanderemo aggiungendo nuove funzioni.


Windows Phone , MVVM

3 comments

Related Post

  1. #1 da Nicola Biancolini Wednesday October 2013 alle 11:17

    Ciao Matteo, grazie per questa serie di post.
    Sto riscontrando un problema nell'instanziazione della classe ViewModelLocator.
    All'interno del file App.xaml è correttamente referenziata, ma non appena viene eseguito il metodo InitializeComponent() viene sollevata l'eccezione System.Windows.Markup.XamlParseException con questo messaggio "Cannot create instance of type 'WeatherShot.ViewModels.ViewModelLocator' [Line: 11 Position: 44]"

  2. #2 da Matteo Pagani Thursday October 2013 alle 01:42

    Ciao Nicola,
    il costruttore della classe ViewModelLocator è pubblico?

  3. #3 da Nicola Biancolini Thursday October 2013 alle 05:39

    Prima no, adesso si ed infatti funziona!


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


  1. #1 da http://enzocontini.wordpress.com/2014/10/13/universal-app/

    Windows Phone 8.1 &#8211; Some useful links for developing Windows &#8220;Universal Apps&#8221; | Enzo Contini Blog