WPF in salsa MVVM e i template

Uno degli aspetti di WPF che più mi piace sono i template. Qui si trova una panoramica su ciò che si può fare.

I DataTemplate sono molto comodi quando usiamo MVVM; a parer mio, sono la risposta alla domanda: "Bene ora ho il ViewModel e la View. Come li relaziono tra loro?".

Come funzionano? Tramite i DataTemplate puoi creare una associazione tra uno specifico tipo di dato ed un template che lo rappresenta. Facciamo qualche esempio: supponiamo di avere un ViewModel di tipo CustomerViewModel e di volerlo associare alla sua View, uno UserControl chiamato CustomerDetailView; potremmo scrivere qualcosa del tipo:

<DataTemplate DataType="{x:Type ViewModel:CustomerViewModel}"> <View:CustomerView /> </DataTemplate>

Supponiamo invece di voler definire direttamente all'interno del DataTemplate la struttura del Template; possiamo farlo, per esempio, in questo modo:

<DataTemplate DataType="{x:Type ViewModel:CustomerViewModel}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> ... </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Text="Company Name" /> <TextBox Grid.Column="1" Text="{Binding Path=CompanyName}" /> ... </Grid> </DataTemplate>

In questo modo siamo andati a definire una regola di questo tipo: "quando ti do un CustomerViewModel tu rappresentalo come questo Template".

Questa regola vale all'interno dello scope di azione del template. Se, per esempio, volessimo che i nostri template siano condivisi da più parti della nostra applicazione, sarà sufficiente inserire la loro definizione all'interno di una ResourceDictionary, da includere nelle nostre Window o nei nostri UserControl. Se invece volessimo usare un determinato template solo per una Window o uno UserControl, basterà definirlo all'interno delle loro risorse locali.

Come facciamo quindi, in definitiva, ad usare questi template? Facciamo l'esempio più semplice ovvero visualizziamo dentro una Window il CustomerViewModel di cui sopra:

<Window x:Class="xxx.Presentation.WPF.UI.View.CustomerView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Window.Resources> <ResourceDictionary Source="../MainResources.xaml" /> </Window.Resources> <DockPanel> <HeaderedContentControl DockPanel.Dock="Top" Content="{Binding Path=Customer}" /> </DockPanel> </Window>

Impostando come proprietà Content dell'HeaderedContentControl il Binding corretto (in questo esempio supponiamo di avere come DataContext della Window una classe che contiene una proprietà Customer di tipo CustomerViewModel), visualizzeremo all'interno della Window il template definito sopra. Ovviamente non è obbligatorio usare un HeaderedContentControl.

L'esempio non è un caso eclatante; passiamo quindi ad un esempio un po' più articolato. Supponiamo di voler realizzare una OrderListView che contiene quindi una lista di ordini, con una sezione dedicata ai dettagli dell'ordine selezionato e che presenti un form di ricerca. Per realizzarla potremmo decidere di creare un ViewModel per ogni entità coinvolta: OrderViewModel, OrderSearchFormViewModel e un OrderListViewModel organizzato più o meno così:

public class OrderListViewModel { public OrderSearchFormViewModel SearchForm { get; set; } public List<OrderViewModel> Orders { get; set; } }

Il processo è poi analogo a quello precedente: ogni ViewModel ha una relativa View; questi sono collegati tra loro con dei DataTemplate. Possiamo quindi costruire uno UserControl in questo modo:

<UserControl x:Class="xxx.Presentation.WPF.UI.View.OrderListView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:View="clr-namespace:xxx.Presentation.WPF.UI.View"> <UserControl.Resources> <ResourceDictionary Source="../MainResources.xaml" /> </UserControl.Resources> <DockPanel> <Grid DockPanel.Dock="Top"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <ContentPresenter Grid.Row="0" Content="{Binding SearchForm}" /> <ListView Grid.Row="1" Name="OrderList" DataContext="{Binding Path=Orders}"> <ListView.View> <GridView> ... </GridView> </ListView.View> </ListView> <ContentPresenter Grid.Row="2" Content="{Binding Path=SelectedItem, ElementName=OrderList}" /> </Grid> </DockPanel> </UserControl>

In questo modo abbiamo creato un controllo che dispone i dati sulle tre righe della grid:

  • visualizzerà sulla prima riga il SearchForm e lo rappresenterà con il DataTemplate relativo
  • la stessa cosa farà per l'ultima riga che verrà visualizzata solo quando selezioniamo un ordine dalla lista
  • la ListView centrale invece provvederà a mostrare tutti gli ordini in una GridView: in questo caso il template viene definito in-line

Infine questo UserControl, che altro non è che la OrderListView, verrà associato a OrderListViewModel sempre tramite un DataTemplate e il giro ricomincia.

Quali sono, a mio parere, i vantaggi di questa soluzione? In sostanza tre:

  • Centralizzare l'associazione tra View e ViewModel, in modo da poterla modificare in un solo punto se necessario
  • La possibilità di legare strettamente il metodo di rappresentazione al tipo rappresentato: se nell'esempio di prima la lista di OrderViewModel contenesse istanze diverse, per esempio StockOrderViewModel e SalesOrderViewModel, rappresentate da View diverse, il ContentPresenter verrebbe rappresentanto sempre con la View corretta senza dover fare nessuna modifica al codice XAML
  • La possibilità di rendere condizionale la scelta del DataTemplate (questo punto lo discuterò in un prossimo post)

 

Matteo

 

Technorati Tag: ,,,

Print | posted @ giovedì 19 febbraio 2009 16:43

Comments on this entry:

Gravatar # re: WPF in salsa MVVM e i template
by Corrado Cavalli at 19/02/2009 18:38

Concordo con te sulle potenzialità dei DataTemplate, peccato che in un mondo 'reale' siano poco applicabili in quanto mal digeriti da tools come Visual Studio e Blend.
Visual Studio proprio non te li fa editare mentre Blend ha una editing experience vicina allo zero quindi per quanto mi riguarda l'utilizzo dei DataTemplate per la renderizzazione dei ViewModel è rimandato fino a quando avrò dei tools all'altezza del classico WYSIWYG. Rimane ovviamente valido il loro utilizzo in tutti gli altri casi minori (es: all'interno di ItemTemplates).
Gravatar # re: WPF in salsa MVVM e i template
by taoruankeji at 19/08/2010 09:23

PDF to TIFF Converter is a professional PDF to images program which let you convert PDF to TIFF and lots of image formats with high quality, such as JPEG, PNG, GIF, BMP, PCX, TGA. As to convert PDF to TIFF, you can freely set output encoder, including lossless, RLE, FAX G3, etc. Using this PDF to TIFF Converter, you alos can choose grey and black/white as output color. Reset resolution is applicable as well.
PDF to XLS Converter
PDF to EPUB Converter
Convert PDF to GIF
Gravatar # re: WPF in salsa MVVM e i template
by DesireeREILLY at 15/07/2011 22:15

I opine that you should buy essay papers with a purpose to forget about your essays problems!
Comments have been closed on this topic.