Controlli come Page e View forniscono proprietà per definirne l’aspetto, la forma e il comportamento all’interno del’app. In particolare, l’aspetto di un controllo può essere gestito attraverso la realizzazione di stili o, più semplicemente, tramite dei template basilari per l’app. Ciononostante, questo approccio non offre una netta separazione tra l’aspetto della pagina e il suo contenuto.
Dalla versione 2.0, Xamarin ha introdotto il componente ControlTemplate, che offre una netta separazione tra l’aspetto e il contenuto di una Page o di una View, permettendo allo sviluppatore di concentrarsi esclusivamente sull’aspetto dei controlli.
Un ControlTemplate può essere applicato ai seguenti tipi di View e Page impostando l’omonima proprietà:
ContentPageContentViewTemplatedPageTemplatedView
dove la TemplatedPage è la classe base per le ContentPage e mostra il contenuto a schermo intero impiegando un ControlTemplate, mentre la TemplatedView è la classe base della ContentView.
Un ControlTemplate può essere definito sia in XAML che in C#:
| XAML | Viene impiegata la proprietà ResourceDictionary che assegna il ControlTemplate creato alla collezione Resources di una pagina (o in generale) dell’app |
|---|---|
| C# | Viene definita una pagina o una classe, che può essere globalmente acceduta |
Inoltre, è possibile applicare un ControlTemplate su due livelli:
- page-level: applicazione solo ad una pagina;
- application-level: applicazione a tutte le pagine dell’app.
La definizione di questi livelli prevede la seguente gerarchia: supponendo di aver definito due differenti ControlTemplate, uno per ogni livello con il medesimo nome, quello definito per l’application-level viene sostituito dal template per il page-level.
Creazione di un ControlTemplate in XAML
La creazione di un template per l’application-level prevede che la classe App del progetto Portable sia sostituita dalla sua implementazione alternativa basata su XMAL e C#. Ciò rende più semplice la creazione di un nuovo template in XAML. La nuova classe App implementerà nel code-behind la classe Application per poter utilizzare la proprietà Resources che conterrà al suo interno il nuovo ControlTemplate.
Nel codice XAML della classe App si definirà il seguente codice:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HelloXamarin.App">
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="HeaderFooterTemplate">
...
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
Attraverso la proprietà Resources di Application è possibile definire un ResourceDictionary, un dizionario di risorse che possono essere impiegate all’interno di un’app Xamarin.Forms e facilmente riutilizzate. Ogni nuova risorsa contenuta nel ResourceDictionary è caratterizzata da una chiave x:Key definita come proprietà dell’elemento che si desidera creare. In questo caso, la chiave è associata al ControlTemplate che definisce al suo interno gli elementi del template.
Ad esempio, si supponga di voler definire per tutte le pagine una schermata composta da un header ed un footer come nella seguente figura:
Il modo più semplice è per implementare tale layout è definire una Grid composta da tre Row, ognuna con una dimensione diversa e due colonne. Inoltre, ogni riga conterrà rispettivamente:
- l’header composto da una
BoxViewche funge da sfondo, unImageracchiusa nella prima colonna e unaLabelracchiusa nella seconda colonna; - un
ContentPresenterche svolge il ruolo di layout manager per i template e definisce dove il contenuto che verrà aggiunto all’interno di ogni singola pagina deve andare, evitando così sovrapposizioni con l’header e il footer; - il footer composto da uno
StackLayoutche farà da contenitore per laLabel. Si noti che alternativamente si può impiegare unaBoxViewcome per l’header e viceversa.
Nel codice XAML si avrà:
<ControlTemplate x:Key="HeaderFooterTemplate">
<Grid BackgroundColor="#003366">
<Grid.RowDefinitions>
<RowDefinition Height="0.1*"/>
<RowDefinition Height="0.85*" />
<RowDefinition Height="0.05*" />
</Grid.RowDefinitions>
<BoxView Grid.ColumnSpan="2" Color="#c7c9cc" />
<Image Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalOptions="Center">
<Image.Source>
<OnPlatform x:TypeArguments="ImageSource"
iOS="logo.png"
Android="logo.png"
WinPhone="Images/logo.png" />
</Image.Source>
</Image>
<Label Grid.Column="0" Text="Header!!!" TextColor="Black" FontSize="22" VerticalOptions="Center" />
<ContentPresenter Grid.Row="1" Grid.ColumnSpan="2" />
<StackLayout Grid.Row="2" Grid.ColumnSpan="2" BackgroundColor="#c7c9cc">
<Label Text="Footer here!" TextColor="Black" FontSize="18" VerticalOptions="CenterAndExpand" HorizontalOptions="Center"/>
</StackLayout>
</Grid>
</ControlTemplate>
Per impostare il ControlTemplate in una pagina dell’applicazione, basterà richiamare l’omonima proprietà. Ad esempio, una volta creata la pagina CTApplicationLevel, nel codice XAML si avrà:
<ContentPage ControlTemplate="{StaticResource HeaderFooterTemplate}">
<StackLayout VerticalOptions="CenterAndExpand">
<Label Text="||| Page content |||" TextColor="Black" FontSize="25" HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
Eseguendo quindi l’app sui tre OS di interesse si otterrà il risultato in figura.
Se per una specifica pagina si volesse impiegare un template differente, ad esempio con colori e posizioni degli elementi invertiti, si potrà definrie un ControlTemplate per la pagina lavora sul codice XAML della pagina stessa. Si supponga quindi di aver creato la pagina CTPageLevel, nel codice XAML si avrà:
<ContentPage.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="HeaderFooterTemplate">
<Grid BackgroundColor="#003366">
. . .
</Grid>
</ControlTemplate>
</ResourceDictionary>
</ContentPage.Resources>
Analogamente a quanto fatto per la nuova classe App, anche qui è necessario richiamare la proprietà Resources della ContentPage e definire all’interno del ResourceDictionary il nuovo template avente come chiave la stessa definita per il template per l’application-level. Effettuando le opportune modifiche ed eseguendo l’applicazione si otterrà il seguente risultato.
Se vuoi aggiornamenti su Development inserisci la tua email nel box qui sotto:


