Technology Experience
.NET World

[5] Il ritorno dello HockeyPlayer (data-binding con WPF)

Proseguo la mia serie di articoli con una piccola riflessione che ho fatto fra me e me ieri sera mentre stavo lavorando. Per spiegarla, riprendo un blocco XAML del post [3] Il ritorno dello HockeyPlayer (data-binding con WPF), nel punto in cui definisco la ListBox che contiene i vari HockeyPlayer:

<ListBox Name="lstPlayers" ItemsSource="{Binding Source={StaticResource players}, Path=HockeyPlayer}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Margin="4" Orientation="Horizontal"> <TextBox Text="{Binding Path=Name}" Margin="4" Width="120" /> <TextBox Margin="4" Text="{Binding Path=Weight}" Background="LightCoral" Width="30" /> <TextBlock Margin="4" Text="{Binding ElementName=sldHeight, Path=Value}" Width="60" /> <Slider Name="sldHeight" Value="{Binding Path=Height}" Minimum="140" Maximum="230" Width="120" /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

Osserviamo come la definizione del template col quale deve essere disegnato ogni Item della ListBox è fatto in corrispondenza della definizione della ListBox stessa. All’interno del tag <ListBox></ListBox> si definisce il DataTemplate, che è composto da uno StackPanel e via dicendo. Questo è quello che sono sempre stato abituato a vedere.

La mia domanda è: posso spostare la definizione del template in uno XAML dedicato? In altre parole, posso creare uno UserControl separato e staccato e poi referenziarlo e riutilizzarlo nel template? La risposta è sì. I motivi possono essere molteplici: se creo uno UserControl, posso utilizzare la stesso oggetto in più punti della mia applicazione, per favorire ad esempio una certa omogeinità nell’interfaccia. Se creo uno UserControl, questo è più facilmente debuggabile. Se creo uno UserControl, il codice XAML è meno prolisso, più leggibile e più facilmente modificabile.

Per farlo, è sufficiente aggiungere al progetto un nuovo UserControl (WPF), dargli il nome che vogliamo (ad esempio, HockeyPlayerTemplate) e copiare all’interno del blocco <UserControl></UserControl> lo XAML che definisce i controlli:

<UserControl x:Class="MyItemTemplate.HockeyPlayerTemplate" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:a="clr-namespace:MyItemTemplate"> <StackPanel Margin="4" Orientation="Horizontal"> <TextBox Margin="4" Width="120" Style="{StaticResource mandatory}" Text="{Binding Path=Name}" /> <TextBox Margin="4" Text="{Binding Path=Weight}" Background="LightCoral" Width="30" /> <TextBlock Margin="4" Text="{Binding ElementName=sldHeight, Path=Value, Converter={StaticResource conv}}" Width="60" /> <Slider Name="sldHeight" Minimum="50" Maximum="200" Width="120" Value="{Binding Path=Height}" /> </StackPanel> </UserControl>

Da notare che il resto è rimasto invariato. Continuo a fare uso del binding, anche se in questo contesto WPF non sa bene a cosa bindare. Non ha importanza, perchè poi a runtime ha tutte le informazioni che gli servono: in particolare, siamo noi che diciamo che ogni elemento della ListBox appartiene alla classe HockeyPlayer. Di conseguenza, il binding sulle proprietà Weight, Height e via dicendo funziona senza alcun problema.

Detto questo, la ListBox può essere definita come segue:

<ListBox Name="lstPlayers" ItemsSource="{Binding Source={StaticResource players}, Path=HockeyPlayer}"> <ListBox.ItemTemplate> <DataTemplate> <a:HockeyPlayerTemplate /> </DataTemplate> </ListBox.ItemTemplate> </ListBox>

Il DataTemplate fa riferimento grazie al prefisso a alla classe HockeyPlayerTemplate, che è proprio lo UserControl che abbiamo appena creato. Questo UserControl, lo ripeto, non solo può essere utilizzato come template per la ListBox, ma in ogni altro punto della nostra applicazione, qualora ci servisse.

Una precisazione. Nello UserControl va aggiunta una risorsa, il converter che abbiamo creato l’ultima volta. Questo converter viene utilizzato nel TextBlock per permettere di leggere il valore dello Slider senza decimali. Non è un problema, basta aprire lo XAML dello UserControl ed aggiungere tra le sue risorse la classe che fa da converter:

<UserControl.Resources> <a:SliderValueConverter x:Key="conv"/> </UserControl.Resources>

Domanda: perchè non dobbiamo inserire anche la risorsa denominata mandatory? Perchè, lo abbiamo visto precedentemente, questa risorsa è stata inserita fra quelle a livello di applicazione, e quindi è globale.

Send to Kindle

Igor Damiani

La sua passione per l'informatica nasce nella prima metà degli anni '80, quando suo padre acquistò un Texas Instruments TI-99. Da allora ha continuato a seguire l'evoluzione sia hardware che software avvenuta nel corso degli anni. E' un utente, un videogiocatore ed uno sviluppatore software a tempo pieno. Igor ha lavorato e lavora anche oggi con le più moderne tecnologie Microsoft per lo sviluppo di applicazioni: .NET Framework, XAML, Universal Windows Platform, su diverse piattaforme, tra cui spiccano Windows 10 piattaforme mobile. Numerose sono le app che Igor ha creato e pubblicato sul marketplace sotto il nome VivendoByte, suo personale marchio di fabbrica. Adora mantenere i contatti attraverso Twitter e soprattutto attraverso gli eventi delle community .NET.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.