Xamarin.Forms šablony ovládacích prvků
Xamarin.Forms Šablony ovládacích prvků umožňují definovat vizuální strukturu odvozených vlastních ovládacích ContentView
prvků a ContentPage
odvozených stránek. Šablony ovládacích prvků oddělují uživatelské rozhraní pro vlastní ovládací prvek nebo stránku od logiky, která implementuje ovládací prvek nebo stránku. Do předdefinovaného umístění lze také vložit další obsah do vlastního ovládacího prvku šablony nebo na stránku šablony.
Můžete například vytvořit šablonu ovládacího prvku, která předefinuje uživatelské rozhraní, které poskytuje vlastní ovládací prvek. Šablonu ovládacího prvku pak může spotřebovat požadovaná instance vlastního ovládacího prvku. Alternativně lze vytvořit šablonu ovládacího prvku, která definuje jakékoli společné uživatelské rozhraní, které bude používat více stránek v aplikaci. Šablonu ovládacího prvku pak může využívat více stránek, přičemž každá stránka stále zobrazuje svůj jedinečný obsah.
Vytvoření ControlTemplate
Následující příklad ukazuje kód vlastního CardView
ovládacího prvku:
public class CardView : ContentView
{
public static readonly BindableProperty CardTitleProperty = BindableProperty.Create(nameof(CardTitle), typeof(string), typeof(CardView), string.Empty);
public static readonly BindableProperty CardDescriptionProperty = BindableProperty.Create(nameof(CardDescription), typeof(string), typeof(CardView), string.Empty);
// ...
public string CardTitle
{
get => (string)GetValue(CardTitleProperty);
set => SetValue(CardTitleProperty, value);
}
public string CardDescription
{
get => (string)GetValue(CardDescriptionProperty);
set => SetValue(CardDescriptionProperty, value);
}
// ...
}
Třída CardView
, která je odvozena z ContentView
třídy, představuje vlastní ovládací prvek, který zobrazuje data v rozložení podobné kartě. Třída obsahuje vlastnosti, které jsou podporovány vazebnými vlastnostmi, pro data, která zobrazí. CardView
Třída však nedefinuje žádné uživatelské rozhraní. Místo toho se uživatelské rozhraní definuje pomocí šablony ovládacího prvku. Další informace o vytváření ContentView
odvozených vlastních ovládacích prvků naleznete v tématu Xamarin.Forms ContentView.
Vytvoří se šablona ovládacího prvku s typem ControlTemplate
. Když vytvoříte objekty ControlTemplate
, zkombinujete View
objekty pro vytvoření uživatelského rozhraní pro vlastní ovládací prvek nebo stránku. A ControlTemplate
musí mít pouze jeden View
jako jeho kořenový prvek. Kořenový prvek však obvykle obsahuje jiné View
objekty. Kombinace objektů tvoří vizuální strukturu ovládacího prvku.
I když lze definovat vložený ControlTemplate
přístup, typický přístup k deklarování ControlTemplate
je jako prostředek ve slovníku prostředků. Protože šablony ovládacích prvků jsou prostředky, dodržují stejná pravidla oborů, která platí pro všechny prostředky. Pokud například deklarujete šablonu ovládacího prvku v kořenovém prvku souboru XAML definice aplikace, můžete šablonu použít kdekoli ve vaší aplikaci. Pokud šablonu definujete na stránce, může použít pouze tuto šablonu ovládacího prvku. Další informace o prostředcích najdete v tématu Xamarin.Forms Slovníky prostředků.
Následující příklad XAML ukazuje ControlTemplate
objekty CardView
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewControlTemplate">
<Frame BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}"
BorderColor="{Binding BorderColor}"
CornerRadius="5"
HasShadow="True"
Padding="8"
HorizontalOptions="Center"
VerticalOptions="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition Height="4" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Frame IsClippedToBounds="True"
BorderColor="{Binding BorderColor}"
BackgroundColor="{Binding IconBackgroundColor}"
CornerRadius="38"
HeightRequest="60"
WidthRequest="60"
HorizontalOptions="Center"
VerticalOptions="Center">
<Image Source="{Binding IconImageSource}"
Margin="-20"
WidthRequest="100"
HeightRequest="100"
Aspect="AspectFill" />
</Frame>
<Label Grid.Column="1"
Text="{Binding CardTitle}"
FontAttributes="Bold"
FontSize="Large"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start" />
<BoxView Grid.Row="1"
Grid.ColumnSpan="2"
BackgroundColor="{Binding BorderColor}"
HeightRequest="2"
HorizontalOptions="Fill" />
<Label Grid.Row="2"
Grid.ColumnSpan="2"
Text="{Binding CardDescription}"
VerticalTextAlignment="Start"
VerticalOptions="Fill"
HorizontalOptions="Fill" />
</Grid>
</Frame>
</ControlTemplate>
</ContentPage.Resources>
...
</ContentPage>
ControlTemplate
Když je deklarován jako prostředek, musí mít klíč zadaný s x:Key
atributem, aby ho bylo možné identifikovat ve slovníku prostředků. V tomto příkladu je kořenovým prvkem objektu CardViewControlTemplate
Frame
. Objekt Frame
používá RelativeSource
rozšíření značek k nastavení jeho BindingContext
na instanci objektu runtime, na kterou se šablona použije, což se označuje jako nadřazený objekt šablony. Objekt Frame
používá kombinaci Grid
, , Image
Frame
, Label
a BoxView
objekty definovat vizuální strukturu objektuCardView
. Vazbové výrazy těchto objektů se přeloží na CardView
vlastnosti, protože dědí BindingContext
z kořenového Frame
elementu. Další informace o RelativeSource
rozšíření značek naleznete v tématu Xamarin.Forms Relativní vazby.
Využití controlTemplate
A ControlTemplate
lze použít na odvozený ContentView
vlastní ovládací prvek nastavením jeho ControlTemplate
vlastnosti na objekt šablony ovládacího prvku. ControlTemplate
Podobně lze použít na odvozenou ContentPage
stránku nastavením jeho ControlTemplate
vlastnosti na objekt šablony ovládacího prvku. Za běhu se při ControlTemplate
použití všech ovládacích prvků definovaných v šabloně ControlTemplate
vlastního ovládacího prvku nebo stránky šablony přidají do vizuálního stromu.
Následující příklad ukazuje CardViewControlTemplate
přiřazení vlastnosti každého CardView
objektuControlTemplate
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
...>
<StackLayout Margin="30">
<controls:CardView BorderColor="DarkGray"
CardTitle="John Doe"
CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Jane Doe"
CardDescription="Phasellus eu convallis mi. In tempus augue eu dignissim fermentum. Morbi ut lacus vitae eros lacinia."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Xamarin Monkey"
CardDescription="Aliquam sagittis, odio lacinia fermentum dictum, mi erat scelerisque erat, quis aliquet arcu."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
</StackLayout>
</ContentPage>
V tomto příkladu se ovládací prvky v rámci CardViewControlTemplate
vizuálního stromu stanou součástí každého CardView
objektu. Vzhledem k tomu, že kořenový Frame
objekt šablony ovládacího prvku nastaví jeho BindingContext
na nadřazenou šablonu, Frame
a její podřízené položky přeloží své vazby výrazy proti vlastnostem každého CardView
objektu.
Následující snímky obrazovky ukazují CardViewControlTemplate
použité na tři CardView
objekty:
Důležité
Bod v čase, který ControlTemplate
se použije na instanci ovládacího prvku, lze zjistit přepsáním OnApplyTemplate
metody v šabloně vlastního ovládacího prvku nebo stránkou šablony. Další informace naleznete v tématu Získání pojmenovaného elementu ze šablony.
Předání parametrů pomocí TemplateBinding
Rozšíření TemplateBinding
značek vytvoří vazbu vlastnosti elementu, který je ve ControlTemplate
veřejné vlastnosti, která je definována šablonou vlastní ovládací prvek nebo stránka šablony. Když použijete TemplateBinding
příkaz , povolíte vlastnosti ovládacího prvku tak, aby fungovaly jako parametry šablony. Proto když je nastavena vlastnost na šabloně vlastní ovládací prvek nebo stránka šablony, tato hodnota je předána do elementu, který má TemplateBinding
na něm.
Důležité
Výraz TemplateBinding
značky RelativeSource
umožňuje odebrat vazbu z předchozí šablony ovládacího prvku a nahradit Binding
výrazy.
Rozšíření TemplateBinding
značek definuje následující vlastnosti:
Path
, typustring
, cesta k vlastnosti.Mode
, typuBindingMode
, směr, ve kterém se změny šíří mezi zdrojem a cílem.Converter
, typuIValueConverter
, převaděč hodnoty vazby.ConverterParameter
, typuobject
, parametr pro převaděč hodnoty vazby.StringFormat
, typustring
, formát řetězce pro vazbu.
TemplateBinding
Pro ContentProperty
rozšíření značek je Path
. Proto lze část "Path=" rozšíření značek vynechat, pokud je cesta první položkou ve výrazu TemplateBinding
. Další informace o použití těchto vlastností ve výrazu vazby naleznete v tématu Xamarin.Forms Datové vazby.
Upozorňující
Rozšíření TemplateBinding
značek by mělo být použito pouze v rámci .ControlTemplate
Pokus o použití výrazu TemplateBinding
mimo objekt ControlTemplate
však nebude mít za následek chybu sestavení nebo vyvolání výjimky.
Následující příklad XAML ukazuje ControlTemplate
objekty CardView
, které používají TemplateBinding
rozšíření značek:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewControlTemplate">
<Frame BackgroundColor="{TemplateBinding CardColor}"
BorderColor="{TemplateBinding BorderColor}"
CornerRadius="5"
HasShadow="True"
Padding="8"
HorizontalOptions="Center"
VerticalOptions="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition Height="4" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Frame IsClippedToBounds="True"
BorderColor="{TemplateBinding BorderColor}"
BackgroundColor="{TemplateBinding IconBackgroundColor}"
CornerRadius="38"
HeightRequest="60"
WidthRequest="60"
HorizontalOptions="Center"
VerticalOptions="Center">
<Image Source="{TemplateBinding IconImageSource}"
Margin="-20"
WidthRequest="100"
HeightRequest="100"
Aspect="AspectFill" />
</Frame>
<Label Grid.Column="1"
Text="{TemplateBinding CardTitle}"
FontAttributes="Bold"
FontSize="Large"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start" />
<BoxView Grid.Row="1"
Grid.ColumnSpan="2"
BackgroundColor="{TemplateBinding BorderColor}"
HeightRequest="2"
HorizontalOptions="Fill" />
<Label Grid.Row="2"
Grid.ColumnSpan="2"
Text="{TemplateBinding CardDescription}"
VerticalTextAlignment="Start"
VerticalOptions="Fill"
HorizontalOptions="Fill" />
</Grid>
</Frame>
</ControlTemplate>
</ContentPage.Resources>
...
</ContentPage>
V tomto příkladu TemplateBinding
rozšíření značek překládá vazby výrazy proti vlastnostem každého CardView
objektu. Následující snímky obrazovky ukazují CardViewControlTemplate
použité na tři CardView
objekty:
Důležité
TemplateBinding
Použití rozšíření značek je ekvivalentní nastavení BindingContext
kořenového prvku v šabloně na jeho šablonované nadřazené objekty s RelativeSource
rozšířením značek a poté překlad vazeb podřízených objektů s rozšířením Binding
značek. Ve skutečnosti TemplateBinding
rozšíření značek vytvoří Binding
, jehož Source
je RelativeBindingSource.TemplatedParent
.
Použití ControlTemplate se stylem
Šablony ovládacích prvků lze použít také se styly. Toho dosáhnete vytvořením implicitního nebo explicitního stylu, který využívá ControlTemplate
.
Následující příklad XAML ukazuje implicitní styl, který využívá CardViewControlTemplate
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewControlTemplate">
...
</ControlTemplate>
<Style TargetType="controls:CardView">
<Setter Property="ControlTemplate"
Value="{StaticResource CardViewControlTemplate}" />
</Style>
</ContentPage.Resources>
<StackLayout Margin="30">
<controls:CardView BorderColor="DarkGray"
CardTitle="John Doe"
CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
IconBackgroundColor="SlateGray"
IconImageSource="user.png" />
<controls:CardView BorderColor="DarkGray"
CardTitle="Jane Doe"
CardDescription="Phasellus eu convallis mi. In tempus augue eu dignissim fermentum. Morbi ut lacus vitae eros lacinia."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"/>
<controls:CardView BorderColor="DarkGray"
CardTitle="Xamarin Monkey"
CardDescription="Aliquam sagittis, odio lacinia fermentum dictum, mi erat scelerisque erat, quis aliquet arcu."
IconBackgroundColor="SlateGray"
IconImageSource="user.png" />
</StackLayout>
</ContentPage>
V tomto příkladu se implicitní Style
automaticky použije u každého CardView
objektu a nastaví ControlTemplate
vlastnost každého CardView
objektu na CardViewControlTemplate
.
Další informace o stylech naleznete v tématu Xamarin.Forms Styly.
Předefinovat uživatelské rozhraní ovládacího prvku
ControlTemplate
Při vytvoření instance a přiřazení k ControlTemplate
vlastnosti odvozeného ContentView
vlastního ovládacího prvku nebo odvozené ContentPage
stránky, vizuální struktura definovaná pro vlastní ovládací prvek nebo stránku se nahradí vizuální strukturou definovanou v sadě ControlTemplate
.
Vlastní ovládací prvek například CardViewUI
definuje své uživatelské rozhraní pomocí následujícího kódu XAML:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ControlTemplateDemos.Controls.CardViewUI"
x:Name="this">
<Frame BindingContext="{x:Reference this}"
BackgroundColor="{Binding CardColor}"
BorderColor="{Binding BorderColor}"
CornerRadius="5"
HasShadow="True"
Padding="8"
HorizontalOptions="Center"
VerticalOptions="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition Height="4" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Frame IsClippedToBounds="True"
BorderColor="{Binding BorderColor, FallbackValue='Black'}"
BackgroundColor="{Binding IconBackgroundColor, FallbackValue='Gray'}"
CornerRadius="38"
HeightRequest="60"
WidthRequest="60"
HorizontalOptions="Center"
VerticalOptions="Center">
<Image Source="{Binding IconImageSource}"
Margin="-20"
WidthRequest="100"
HeightRequest="100"
Aspect="AspectFill" />
</Frame>
<Label Grid.Column="1"
Text="{Binding CardTitle, FallbackValue='Card title'}"
FontAttributes="Bold"
FontSize="Large"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start" />
<BoxView Grid.Row="1"
Grid.ColumnSpan="2"
BackgroundColor="{Binding BorderColor, FallbackValue='Black'}"
HeightRequest="2"
HorizontalOptions="Fill" />
<Label Grid.Row="2"
Grid.ColumnSpan="2"
Text="{Binding CardDescription, FallbackValue='Card description'}"
VerticalTextAlignment="Start"
VerticalOptions="Fill"
HorizontalOptions="Fill" />
</Grid>
</Frame>
</ContentView>
Ovládací prvky, které tvoří toto uživatelské rozhraní, lze však nahradit definováním nové vizuální struktury v objektu ControlTemplate
a jeho přiřazením k ControlTemplate
vlastnosti objektu CardViewUI
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
...>
<ContentPage.Resources>
<ControlTemplate x:Key="CardViewCompressed">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="{TemplateBinding IconImageSource}"
BackgroundColor="{TemplateBinding IconBackgroundColor}"
WidthRequest="100"
HeightRequest="100"
Aspect="AspectFill"
HorizontalOptions="Center"
VerticalOptions="Center" />
<StackLayout Grid.Column="1">
<Label Text="{TemplateBinding CardTitle}"
FontAttributes="Bold" />
<Label Text="{TemplateBinding CardDescription}" />
</StackLayout>
</Grid>
</ControlTemplate>
</ContentPage.Resources>
<StackLayout Margin="30">
<controls:CardViewUI BorderColor="DarkGray"
CardTitle="John Doe"
CardDescription="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla elit dolor, convallis non interdum."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewCompressed}" />
<controls:CardViewUI BorderColor="DarkGray"
CardTitle="Jane Doe"
CardDescription="Phasellus eu convallis mi. In tempus augue eu dignissim fermentum. Morbi ut lacus vitae eros lacinia."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewCompressed}" />
<controls:CardViewUI BorderColor="DarkGray"
CardTitle="Xamarin Monkey"
CardDescription="Aliquam sagittis, odio lacinia fermentum dictum, mi erat scelerisque erat, quis aliquet arcu."
IconBackgroundColor="SlateGray"
IconImageSource="user.png"
ControlTemplate="{StaticResource CardViewCompressed}" />
</StackLayout>
</ContentPage>
V tomto příkladu je vizuální struktura objektu CardViewUI
předdefinována, ControlTemplate
která poskytuje kompaktnější vizuální strukturu, která je vhodná pro zhuštěný seznam:
Nahrazení obsahu do ContentPresenteru
Šablonu ContentPresenter
ovládacího prvku lze umístit do šablony ovládacího prvku a označit tak, kde se zobrazí obsah, který se má zobrazit pomocí vlastního ovládacího prvku nebo stránky šablony. Vlastní ovládací prvek nebo stránka, která využívá šablonu ovládacího prvku, pak definuje obsah, který se má zobrazit pomocí ContentPresenter
. Následující diagram znázorňuje ControlTemplate
stránku, která obsahuje řadu ovládacích prvků včetně ContentPresenter
označeného modrým obdélníkem:
Následující xaml ukazuje šablonu ovládacího prvku s názvem TealTemplate
, která obsahuje ContentPresenter
ve své vizuální struktuře:
<ControlTemplate x:Key="TealTemplate">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="0.1*" />
<RowDefinition Height="0.8*" />
<RowDefinition Height="0.1*" />
</Grid.RowDefinitions>
<BoxView Color="Teal" />
<Label Margin="20,0,0,0"
Text="{TemplateBinding HeaderText}"
TextColor="White"
FontSize="Title"
VerticalOptions="Center" />
<ContentPresenter Grid.Row="1" />
<BoxView Grid.Row="2"
Color="Teal" />
<Label x:Name="changeThemeLabel"
Grid.Row="2"
Margin="20,0,0,0"
Text="Change Theme"
TextColor="White"
HorizontalOptions="Start"
VerticalOptions="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="OnChangeThemeLabelTapped" />
</Label.GestureRecognizers>
</Label>
<controls:HyperlinkLabel Grid.Row="2"
Margin="0,0,20,0"
Text="Help"
TextColor="White"
Url="https://learn.microsoft.com/xamarin/xamarin-forms/"
HorizontalOptions="End"
VerticalOptions="Center" />
</Grid>
</ControlTemplate>
Následující příklad ukazuje TealTemplate
přiřazenou ControlTemplate
vlastnost odvozené ContentPage
stránky:
<controls:HeaderFooterPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
ControlTemplate="{StaticResource TealTemplate}"
HeaderText="MyApp"
...>
<StackLayout Margin="10">
<Entry Placeholder="Enter username" />
<Entry Placeholder="Enter password"
IsPassword="True" />
<Button Text="Login" />
</StackLayout>
</controls:HeaderFooterPage>
Při použití na stránku za běhu TealTemplate
se obsah stránky nahradí ContentPresenter
definovaným v šabloně ovládacího prvku:
Získání pojmenovaného elementu ze šablony
Pojmenované prvky v rámci šablony ovládacího prvku lze načíst ze šablony vlastního ovládacího prvku nebo šablony stránky. Toho lze dosáhnout pomocí GetTemplateChild
metody, která vrátí pojmenovaný prvek v instanci ControlTemplate
vizuální strom, pokud je nalezen. V opačném případě se vrátí null
.
Po vytvoření instance šablony ovládacího prvku se volá metoda šablony OnApplyTemplate
. Metoda GetTemplateChild
by proto měla být volána z OnApplyTemplate
přepsání v ovládacím prvku šablony nebo šablonované stránce.
Důležité
Metoda GetTemplateChild
by měla být volána pouze po OnApplyTemplate
zavolání metody.
Následující XAML ukazuje šablonu ovládacího prvku s názvem TealTemplate
, kterou lze použít na ContentPage
odvozené stránky:
<ControlTemplate x:Key="TealTemplate">
<Grid>
...
<Label x:Name="changeThemeLabel"
Grid.Row="2"
Margin="20,0,0,0"
Text="Change Theme"
TextColor="White"
HorizontalOptions="Start"
VerticalOptions="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="OnChangeThemeLabelTapped" />
</Label.GestureRecognizers>
</Label>
...
</Grid>
</ControlTemplate>
V tomto příkladu Label
je element pojmenovaný a lze jej načíst v kódu pro stránku se šablonou. Toho dosáhnete voláním GetTemplateChild
metody z OnApplyTemplate
přepsání pro stránku šablony:
public partial class AccessTemplateElementPage : HeaderFooterPage
{
Label themeLabel;
public AccessTemplateElementPage()
{
InitializeComponent();
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
themeLabel = (Label)GetTemplateChild("changeThemeLabel");
themeLabel.Text = OriginalTemplate ? "Aqua Theme" : "Teal Theme";
}
}
V tomto příkladu se po changeThemeLabel
vytvoření instance objektu Label
načteControlTemplate
. changeThemeLabel
je pak možné přistupovat ke třídě a manipulovat s nimi AccessTemplateElementPage
. Následující snímky obrazovky ukazují, že došlo ke změně textu zobrazeného uživatelem Label
:
Vytvoření vazby k modelu viewmodel
A ControlTemplate
může vytvořit vazbu dat na model viewmodel, i když ControlTemplate
vazby k nadřazené šabloně (instance objektu runtime, na kterou je šablona použita).
Následující příklad XAML ukazuje stránku, která využívá model viewmodel s názvem PeopleViewModel
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ControlTemplateDemos"
xmlns:controls="clr-namespace:ControlTemplateDemos.Controls"
...>
<ContentPage.BindingContext>
<local:PeopleViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<DataTemplate x:Key="PersonTemplate">
<controls:CardView BorderColor="DarkGray"
CardTitle="{Binding Name}"
CardDescription="{Binding Description}"
ControlTemplate="{StaticResource CardViewControlTemplate}" />
</DataTemplate>
</ContentPage.Resources>
<StackLayout Margin="10"
BindableLayout.ItemsSource="{Binding People}"
BindableLayout.ItemTemplate="{StaticResource PersonTemplate}" />
</ContentPage>
V tomto příkladu BindingContext
je stránka nastavená na PeopleViewModel
instanci. Tento model zobrazení zveřejňuje kolekci People
a pojmenovanou ICommand
DeletePersonCommand
. Na StackLayout
stránce se používá rozložení s možností vazby k datům v People
kolekci a ItemTemplate
rozložení s možností vázání je nastaveno na PersonTemplate
prostředek. Určuje DataTemplate
, že každá položka v People
kolekci bude zobrazena pomocí objektu CardView
. Vizuální struktura objektu CardView
je definována pomocí pojmenované ControlTemplate
CardViewControlTemplate
:
<ControlTemplate x:Key="CardViewControlTemplate">
<Frame BindingContext="{Binding Source={RelativeSource TemplatedParent}}"
BackgroundColor="{Binding CardColor}"
BorderColor="{Binding BorderColor}"
CornerRadius="5"
HasShadow="True"
Padding="8"
HorizontalOptions="Center"
VerticalOptions="Center">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="75" />
<RowDefinition Height="4" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Text="{Binding CardTitle}"
FontAttributes="Bold"
FontSize="Large"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start" />
<BoxView Grid.Row="1"
BackgroundColor="{Binding BorderColor}"
HeightRequest="2"
HorizontalOptions="Fill" />
<Label Grid.Row="2"
Text="{Binding CardDescription}"
VerticalTextAlignment="Start"
VerticalOptions="Fill"
HorizontalOptions="Fill" />
<Button Text="Delete"
Command="{Binding Source={RelativeSource AncestorType={x:Type local:PeopleViewModel}}, Path=DeletePersonCommand}"
CommandParameter="{Binding CardTitle}"
HorizontalOptions="End" />
</Grid>
</Frame>
</ControlTemplate>
V tomto příkladu je kořenovým prvkem objektu ControlTemplate
Frame
. Objekt Frame
používá RelativeSource
rozšíření značek k nastavení jeho BindingContext
na šablonované nadřazené. Vazbové výrazy objektu Frame
a jeho podřízené položky se přeloží proti CardView
vlastnostem, protože dědí BindingContext
z kořenového Frame
elementu. Následující snímky obrazovky ukazují stránku zobrazující People
kolekci, která se skládá ze tří položek:
Zatímco objekty v vazbě ControlTemplate
na vlastnosti v nadřazené šabloně, Button
v rámci šablony ovládacího prvku vytvoří vazbu na jeho šablony nadřazené objekty a DeletePersonCommand
v modelu viewmodel. Důvodem je, že Button.Command
vlastnost předekfinuje svůj zdroj vazby jako kontext vazby nadřazeného objektu, jehož typ vazby je PeopleViewModel
, což je StackLayout
. Část Path
vazebních výrazů pak může tuto vlastnost přeložit DeletePersonCommand
. Button.CommandParameter
Vlastnost však nezmění svůj zdroj vazby, ale dědí ho z nadřazeného objektu v objektu ControlTemplate
. Proto vlastnost CommandParameter
vytvoří vazbu na CardTitle
vlastnost CardView
.
Celkový účinek Button
vazeb spočívá v tom, že při klepnutí, Button
DeletePersonCommand
ve PeopleViewModel
třídě se spustí hodnota CardName
vlastnosti, která se předává do objektu DeletePersonCommand
. Výsledkem je odebrání zadaného CardView
rozložení s možností vytvoření vazby:
Další informace o relativních vazbách naleznete v tématu Xamarin.Forms Relativní vazby.