ASP.Net  »  Articoli  »  Silverlight 

MVVM: Applicare il pattern in progetti Silverlight

di: Andrea Boschin     28 Aprile 2010

La View

La view, come già detto, altro non è che una parte dell'interfaccia. In questo caso, e nella stragrande maggioranza dei casi, si tratta di uno UserControl, ma può essere anche una ChildWindow oppure spesso anche solamente una riga di una DataGrid.

Questo esempio di markup contiene un ItemsControl, cioè un controllo che è in grado di visualizzare il contenuto di una collection. Esso infatti è collegato alla proprietà "Products" del ViewModel. L'ultima cosa che manca alla prima parte dell'esempio è come fare a collegare tra loro le tre componenti di questo piccolo ecosistema.

Fondamentalmente effettueremo questa operazione ovunque sia necessario istanziare una nuova View. Talvolta questa operazione sarà supportata dall'uso di speciali servizi "container" che sono in grado di istanziare le varie parti grazie a opportune configurazioni. È il caso ad esempio degli Inversion of Control containers. Tuttavia in questo esempio ci limiteremo a scrivere qualche semplice riga di codice.

private void Application_Startup(object sender, StartupEventArgs e)
{
  IProductRepository repository = RepositoryFactory.CreateProduct();
  ProductViewModel vm = new ProductViewModel(repository);
  this.RootVisual = new MainPage { DataContext = vm };
}

In questo snippet dapprima si istanzia il Model. In seguito esso è associato al ViewModel mediante il costruttore della classe. Per come è fatto il ViewModel, questa operazione provocherà il caricamento dei prodotti. Quindi si associa il ViewModel impostando la proprietà DataContext della View. Il risultato sarà che grazie al DataBinding la View verrà popolata con i prodotti provenienti dal Model.

Dalla View al ViewModel: Prism

Con la parte precedente dell'esempio abbiamo preso in considerazione solamente metà del problema. Infatti se è chiaro come attingere alla sorgente dati per popolare la View, non è altrettanto chiaro come intercettare l'interazione dell'utente per provocare modifiche ai dati.

Poniamo ad esempio di voler aggiungere una TextBox e un Pulsante per fare in modo di consentire all'utente di impostare la chiave di ricerca e avviare una nuova ricerca. Il problema, come già anticipato, è che in Silverlight non esiste il concetto di "comando" che invece è presente in WPF.

Per poter chiudere il cerchio dobbiamo fare uso di una libreria esterna rilasciata da Microsoft chiamata Prism. All'interno della libreria si trova una classe DelegateCommand che ci servirà allo scopo.

Una volta referenziato l'assembly Microsoft.Practices.Composite.Presentation.dll è possibile modificare opportunamente il ViewModel. Si aggiungono innanzitutto due proprietà:

public string SearchKey { get; set; }
public DelegateCommand<object> SearchCommand { get; set; }

La prima riceverà il testo digitato nella TextBox. La seconda invece è l'istanza del DelegateCommand che corrisponde all'azione della ricerca. Questo consente di usare il DataBinding anche per collegare il comando all'apposito controllo garantendo un disaccoppiamento fortissimo. Ma una cosa alla volta. Ora è necessario esaminare la logica necessaria:

public ProductViewModel(IProductRepository repository)
{
  this.Repository = repository;
  this.Products = new ObservableCollection<Product>();
  
  this.SearchCommand = new DelegateCommand<object>(this.Search); 
  
  this.Load(string.Empty);
}

private void Search(object payload)
{
  this.Load(this.SearchKey);
}

Il DelegateCommand viene inizializzato con un riferimento ad un metodo che effettua la ricerca. In questo modo, ogni volta che il comando è ricevuto dall'interfaccia, la collection Products viene ricaricata con una diversa selezione di prodotti e questa verrà mostrata nell'interfaccia. Ecco infine il codice di markup modificato:

<UserControl x:Class="SilverlightApplication1.MainPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:cmd="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
             mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

  <Grid x:Name="LayoutRoot">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
      </Grid.RowDefinitions>
    </Grid>
    
    <ItemsControl ItemsSource="{Binding Products}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <TextBlock Text="{Binding Name}" />
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
    
    <StackPanel Grid.Row="1">
      <TextBlock Text="{Binding SearchKey, Mode=TwoWay}" Width="100" />
      <Button cmd:Click.Command="{Binding SearchCommand}" Content="Search" />
    </StackPanel>
  </Grid>
</UserControl>

La parte interessante da notare è l'uso di una Attached Property per collegare il comando al pulsante. Prism purtroppo definisce un solo tipo di attached property con cui si può collegare un comando all'evento click di un pulsante. È tuttavia possibile creare comandi personalizzati per qualsiasi tipo di evento. Il tipo dichiarato in T è quello del parametro (qui inutilizzato) che si può specificare usando la proprietà CommandParameter alla stregua del comando stesso.

Guide ASP.Net

Guida Windows Azure Code Snippets

Le migliori pratiche per far girare le applicazioni "in the cloud",...

Guida ASP.NET MVC Best Practices

Un workflow dettagliato e ricco di suggerimenti pratici per...

Guida ASP.NET Starter Kit

Un modo semplice per imparare ad utilizzare le tecnologie Microsoft...

Altre guide

Newsletter @Microsoft Dev

Ogni giovedì, direttamente nella tua e-mail: articoli, guide, tutorial e script ASP, ASP.Net, SQL server e IIS.

Iscriviti alla newsletter

Altre newsletter

Corsi in aula

Corso Progettazione database

11 Maggio 2012 a Milano
Disponibilità: 6 Posti

Amministratore di Reti Windows Server 2008

11 Giugno 2012 a Milano
Disponibilità: 5 Posti

Nessun corso previsto