Le problematiche più comuni di un'architettura M-V-VM con WPF
di Cristian Civera, in Windows Presentation Foundation, 6 ottobre 2009
Archiviato in: .NET Framework, .NET Framework 3.0, .NET Framework 3.5, Architettura, Windows Presentation Foundation, XAML, Pattern
Ottenere le instanze del ViewModel
Con i primi passi nel mondo dell'architettura basata su M-V-VM si apprende come il ViewModel sia un oggetto funzionale alla View. E' quest'ultima che in genere lo istanzia e lo imposta come DataContext in modo da sfruttare il data binding per il caricamento di dati, l'esecuzione di comandi e animazioni. La tecnica più semplice per fare ciò consiste nell'istanziare il VM nel costruttore e impostarlo nel contesto:
public partial class MainWindow : Window, IMessageRecipient { public MainWindow() { this.DataContext = new MainViewModel(); } }
In alternativa si può fare la stessa cosa sfruttando il markup XAML, funzionante anche all'interno di Expression Blend:
<Window x:Class="CustomersApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:CustomersApplication.ViewModel"> <Window.DataContext> <vm:MainViewModel /> </Window.DataContext>
Durante lo sviluppo di un'applicazione è però difficile pianificare e individuare esattamente le unità logiche e suddividere correttamente i vari VM. In certe circostanze è poi inevitabile dover accedere ad un altro VM per ottenere informazioni o eseguire su di esso delle operazioni. Anche dalla View a volte è necessario invocare metodi sul rispettivo VM, perché non è magari possibile passare attraverso i comandi e per semplificare, se le circostante lo permettono, si scrivono poche righe di codice nella View.
Per accedere a VM sottostante occorre quindi fare il cast del DataContext sul tipo specifico e interrogare le informazioni che interessano. Questo purtroppo non è sempre possibile farlo, perché per esempio non è possibile accedere alla View da un ipotetico VM.
Toolkit come WPF Toolkit e MVVM Light Toolkit propongono due soluzioni molto simili tra loro che sostanzialmente centralizzano la creazione dei ViewModel e permettono di accedervi attraverso proprietà statiche. In pratica un'ipotetica classe ViewModelLocator, visibile da View e VM, può contenere una proprietà statica Main di tipo MainViewModel che mantiene un'unica istanza accessibile da qualsiasi punto dell'applicazione.
public static class ViewModelLocator
public static class ViewModelLocator { private static MainViewModel _main; public static MainViewModel Main { get { if (_main == null) _main = new MainViewModel(); return _main; } }
L'utilizzo all'interno della View si traduce in una singola riga che si appoggia alla markup extension x:Static:
<Window x:Class="CustomersApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:CustomersApplication.ViewModel" DataContext="{Binding Source={x:Static vm:ViewModelLocator.Main}}">
Tutto questo purtroppo non è ancora sufficiente se si vuole avere un supporto a design time con Expression Blend. Occorre infatti usare il ViewModelLocator come una risorsa; basta quindi rendere la classe anche di istanza creando proprietà ponte sui membri statici:
public class ViewModelLocator { // codice dell'esempio precedente public MainViewModel Main { get { return MainStatic; } } }
Cambia inoltre leggermente l'utilizzo nel markup: prima di tutto a livello di applicazione si istanzia l'oggetto così da renderlo disponibile per tutte le View.
<Application x:Class="CustomersApplication.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:CustomersApplication.ViewModel"> <Application.Resources> <vm:ViewModelLocator x:Key="locator" /> </Application.Resources> </Application>
Nella View poi il DataContext si imposta usando la risorsa e appongiandosi alla proprietà di istanza Main che fa da ponte su MainStatic, ottenendo il pieno supporto a design time di Expression Blend.
DataContext="{Binding Main,Source={StaticResource locator}}"L'aspetto interessante di questo è approccio è che in certe situazioni, sebbene la View possa morire perché non più visualizzata, il relativo VM continua a funzionare e a mantenere lo stato (elementi selezionati, operazioni in corso) che l'utente si ritrova non appena la View riparte.
Purtroppo questo è anche il punto critico perché in certe circostanze il ciclo di vita del ViewModel non deve essere perenne, ma gestito secondo certe logiche, o morire non appena la sua utilità è terminata.
Attenzione: Questo articolo contiene un allegato.
Contenuti dell'articolo
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimeti
-
Introduzione a Team Foundation Server 2010
-
Multithreading e parallelismo con il .NET Framework 4.0
-
Le novità nel .NET Framework 4.0 di WPF, WCF e WF
-
Le novità di Visual Basic 2010 e C# 4
-
Mostrare le camere di sorveglianza tramite il .NET Micro Framework
-
La piattaforma Microsoft per il cloud computing: Windows Azure
-
Interoperabilità con WCF: invocare servizi da PHP e Flash
-
Le novità di Windows 7 per gli sviluppatori
-
Costruire una chat per Silverlight con il PollingDuplexHttpBinding

Commenti
mi piace
non mi piace
Facebook
Twitter









