In questa lezione, verrà illustrato nel dettaglio come impiegare i DataTemplate
per personalizzare l’aspetto degli elementi di una ListView
.
Introduzione
Un DataTemplate
permette di uniformare l’aspetto di una collezione di dati contenuti ad esempio in una ListView
. Si supponga di voler mostrare una lista di guide informatiche definite da un titolo, un autore e un numero di lezioni definite nella classe Guide
(disponibile su GitHub).
Per impostare un layout personalizzato per i dati da mostrare, si impiega la proprietà ItemTemplate
di ListView
, impostando come valore il DataTemplate
che conterrà gli elementi da collegare ai valori delle proprietà degli elementi da mostrare. Un DataTemplate
può essere impostato non solo come valore della proprietà ItemTemplate
ma anche per le seguenti proprietà:
Proprietà | Descrizione |
---|---|
HeaderTemplate |
imposta il template per l’header della lista |
FooterTemplate |
imposta il template per il footer della lista |
GroupHeaderTemplate |
definisce il template per l’header che raggruppa gli elementi di una lista |
Xamarin offre la possibilità di definire e applicare un DataTemplate
su diversi livelli. In particolare, si ha:
Livello | Descrizione |
---|---|
inline template | è applicato come valore di una delle proprietà della ListView |
control-level | può essere applicato solo a quel controllo |
page-level | può essere applicato a diversi controlli definiti nella pagina |
application-level | può essere applicato a diversi controlli definiti in tutta l’applicazione |
Creazione di un DataTemplate inline
Per definire un HeaderTemplate
in XAML basterà definire all’interno della ListView
:
<ListView.HeaderTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal" BackgroundColor="Green" HorizontalOptions="CenterAndExpand">
<Label Text="~~"/>
<Label Text=" {Binding .}" FontSize="20"/>
<Label Text="~~"/>
</StackLayout>
</DataTemplate>
</ListView.HeaderTemplate>
Impiegando il medesimo layout per il footer, si avrà:
<ListView.FooterTemplate>
<DataTemplate>
<!-- Same Layout Header -->
</DataTemplate>
</ListView.FooterTemplate>
Infine, per la presentazione dei dati contenuti all’interno della lista, si deve assegnare alla proprietà ItemTemplate
il nuovo DataTemplate
di interesse, come nel seguente esempio:
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label Text="{Binding Title}" FontAttributes="Bold" FontSize="15"/>
<Label Grid.Column="1" Text="{Binding Author}" FontAttributes="Italic" FontSize="15"/>
<Label Grid.Row="1" Text="{Binding Lessons}" FontSize="15"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
In particolare, attraverso la ViewCell
si definirà il nuovo layout della Cell
da mostrare all’utente con i dati opportunamente caricati. In questo caso, è stata definita una Grid
composta da tre Label
rappresentanti le proprietà della classe Guide
.
Creazione di un DataTemplate page-level
Per definire un template per la pagina, è necessario lavorare con la proprietà Resources
della ContentPage
. In particolare, come valore della proprietà ResourceDictionary
andrà impostato il DataTemplate
desiderato e si dovrà definire la proprietà x:Key
che conterrà il nome per impostare il template negli elementi.
Ad esempio, supponendo di utilizzare solo il template definito per i dati contenuti nella lista, si avrà:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="guideCellTemplate">
<ViewCell>
<Grid>
. . .
</Grid>
</ViewCell>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
Successivamente, per applicare il template, si imposta la proprietà ItemTemplate
come segue:
<ListView x:Name="list" ItemTemplate="{StaticResource guideCellTemplate}"/>
Eseguendo l’app, si otterrà il seguente risultato.
Creazione di un DataTemplateSelector
La classe DataTemplate
permette di definire un selettore di template sulla base di una proprietà dei dati da presentare. Ad esempio, si possono definire tre template per evidenziare la lunghezza delle guide offerte attraverso l’impiego di tre diversi colori.
Per prima cosa, si deve creare una classe che imposti il template corretto dinamicamente in base al numero di lezioni. In questo caso, si definisce la classe GuideDTSelector
che sovrascriverà il metodo OnSelectTemplate
come segue:
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
int lessons = ((Guide)item).Lessons;
return lessons < 30 ? ShortGuideTemplate : lessons<=100 ? MediumGuideTemplate : LongGuideTemplate;
}
Così facendo, se il numero di lezioni è minore di 30 verrà applicato il ShortGuideTemplate
, se sono tra 30 e 100 sarà usato il MediumGuideTemplate
, altrimenti il LongGuideTemplate
. Si riporta al seguente link l’implementazione completa della classe.
Non resta che definire i tre template come risorsa della ContentPage
, come mostrato nel codice sottostante. Per semplicità, si riporta solo la definizione del ShortGuideTemplate
, mentre l’implementazione completa è reperibile su GitHub.
<ContentPage . . .
xmlns:local="clr-namespace:HelloXamarin.DataTemplateTest;assembly=HelloXamarin">
<ContentPage.Resources>
<ResourceDictionary>
. . .
<DataTemplate x:Key="shortGuideTemplate">
<ViewCell>
<Grid>
<Label Text="{Binding Title}" FontAttributes="Bold" FontSize="15" TextColor="Green"/>
<Label Grid.Column="1" Text="{Binding Author}" FontAttributes="Italic" FontSize="15" TextColor="Green"/>
<Label Grid.Row="1" Text="{Binding Lessons}" FontSize="15" TextColor="Green"/>
</Grid>
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="mediumGuideTemplate">
. . .
</DataTemplate>
<DataTemplate x:Key="longGuideTemplate">
. . .
</DataTemplate>
<local:GuideDTSelector x:Key="guideDTSelector"
ShortGuideTemplate="{StaticResource shortGuideTemplate}"
MediumGuideTemplate="{StaticResource mediumGuideTemplate}"
LongGuideTemplate="{StaticResource longGuideTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
<ListView x:Name="list" ItemTemplate="{StaticResource guideDTSelector }"/>
</ContentPage>
Si noti che è stato definito come risorsa anche l’elemento GuideDTSelector
che è composto da una chiave e dai tre template. Il selettore sarà, infine, impostato come valore della proprietà ItemTemplate
e permetterà di selezionare il template automaticamente.
Nella seguente figura è riportato il risultato finale.