di: Andrea Boschin 28 Aprile 2010
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.
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.
Guida Windows Azure Code SnippetsLe migliori pratiche per far girare le applicazioni "in the cloud",... |
Guida ASP.NET MVC Best PracticesUn workflow dettagliato e ricco di suggerimenti pratici per... |
Guida ASP.NET Starter KitUn modo semplice per imparare ad utilizzare le tecnologie Microsoft... |
Ogni giovedì, direttamente nella tua e-mail: articoli, guide, tutorial e script ASP, ASP.Net, SQL server e IIS.
Iscriviti alla newsletter
|
|
Corso Progettazione database11 Maggio 2012 a Milano |
|
|
Amministratore di Reti Windows Server 200811 Giugno 2012 a Milano |
|
Nessun corso previsto |