Blog Stats
  • Posts - 171
  • Articles - 1
  • Comments - 197
  • Trackbacks - 5

 

Tuesday, August 3, 2010

MVVM Light Toolkit Generic Locator

Per chi sviluppa applicazioni con WPF è ormai consolidato e direi un “must” applicare il MVVM(model view view model) pattern, di cui esistono diversi articoli, post e framework che ne semplificano l’implementazione.

Attualmente sto utilizzando il MVVM Light Toolkit di Galasoft, e per il momento mi sembra un framework realmente leggero e che fornisce le componenti base che servono per poter cominciare seriamente un progetto WPF.

Questo toolkit utilizza una classe che si chiama ViewModelLocator la quale si occupa di creare una istanza statica del ViewModel attraverso il meccanismo di binding sul datacontext della window principale.Per la precisione, riprendo la definizione di questa classe direttamente dal sito:
“Create a new ViewModelLocator, a class that holds and manages references to ViewModels.”

Il locator viene inserito nell’ App.xaml come risorsa:

<Application.Resources>
  <vm:ViewModelLocator x:Key="Locator"  d:IsDataSource="True" />
</Application.Resources>

Nella MainWindow.xaml, la window principale viene assegnato il DataContext attraverso il binding al locator e alla proprieta Main che altro non è che il ViewModel principale:

DataContext="{Binding Main, Source={StaticResource Locator}}"

Tutto questo va bene, ma cosa succede se nella nostra applicazione wpf abbiamo altre Windows, come per esempio potrebbero essere delle maschere di dettaglio per un classico data-entry ?

Volendo mantenere e riutilizzare il sistema impostato da GalaSoft, ogni Window dovrà avere una classe Locator che crea il binding tra la window ed il suo View Model.

La soluzione che ho adottato è stata quella di creare una classe ViewModelLocator generica e di creare per ogni locator una nuova classe derivante da questa, ma con il pregio di non dover scrivere nessuna riga di codice aggiuntiva.

ViewModelLocatorEx:

using System;

namespace ViewModel.Base
{
    
    public class ViewModelLocatorEx<T> where T : ViewModelBase, new()
    {
        private static T _main;

        public ViewModelLocatorEx()
        {           
            CreateMain();
        }

        public static T MainStatic
        {
            get
            {
                if (_main == null)
                {
                    CreateMain();
                }

                return _main;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage ("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This non-static member is needed for data binding purposes.")]
        public T Main
        {
            get
            {
                return MainStatic;
            }
        }

        public static void ClearMain()
        {
            _main.Cleanup();
            _main = null;
        }

        public static void CreateMain()
        {
            if (_main == null)
            {
                _main = new T();
            }
        }

        public static void Cleanup()
        {
            ClearMain();
        }
    }
}

Ogni window, compresa quella principale, avrà il suo locator cosi definito:

using System;

namespace ViewModel.Locatorsl
{
  
    public class MainViewModelLocator : ViewModelLocatorEx<MainViewModel>
    {
    }

}

Per ultimo dovranno essere dichiarati tutti i locators nell’ app.xaml come visto sopra, quindi per esempio:

<Application.Resources>
        <vm:MainViewModelLocator x:Key="Locator" d:IsDataSource="True" />
        ...
        <vm:OtherViewModelLocator x:Key="Locator2" d:IsDataSource="True" />
        ...
</Application.Resources>

Hope this helps…

del.icio.us Tags: ,,

 

 

 

Copyright © Luca Mauri