Xamarin.Forms templat kontrol
Xamarin.Forms templat kontrol memungkinkan Anda menentukan struktur visual kontrol kustom turunan ContentView
, dan ContentPage
halaman turunan. Templat kontrol memisahkan antarmuka pengguna (UI) untuk kontrol kustom, atau halaman, dari logika yang mengimplementasikan kontrol atau halaman. Konten tambahan juga dapat disisipkan ke dalam kontrol kustom templat, atau halaman templat, di lokasi yang telah ditentukan sebelumnya.
Misalnya, templat kontrol dapat dibuat yang mendefinisikan ulang UI yang disediakan oleh kontrol kustom. Templat kontrol kemudian dapat digunakan oleh instans kontrol kustom yang diperlukan. Atau, templat kontrol dapat dibuat yang menentukan antarmuka pengguna umum yang akan digunakan oleh beberapa halaman dalam aplikasi. Templat kontrol kemudian dapat digunakan oleh beberapa halaman, dengan setiap halaman masih menampilkan konten uniknya.
Membuat ControlTemplate
Contoh berikut menunjukkan kode untuk CardView
kontrol kustom:
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);
}
// ...
}
Kelas CardView
, yang berasal dari ContentView
kelas , mewakili kontrol kustom yang menampilkan data dalam tata letak seperti kartu. Kelas berisi properti, yang didukung oleh properti yang dapat diikat, untuk data yang ditampilkannya. Namun, CardView
kelas tidak menentukan UI apa pun. Sebagai gantinya, UI akan didefinisikan dengan templat kontrol. Untuk informasi selengkapnya tentang membuat ContentView
kontrol kustom turunan, lihat Xamarin.Forms ContentView.
Templat kontrol dibuat dengan jenis .ControlTemplate
Saat Anda membuat ControlTemplate
, Anda menggabungkan View
objek untuk membangun UI untuk kontrol kustom, atau halaman. Harus ControlTemplate
memiliki hanya satu View
sebagai elemen akarnya. Namun, elemen root biasanya berisi objek lain View
. Kombinasi objek membentuk struktur visual kontrol.
ControlTemplate
Meskipun dapat didefinisikan sebaris, pendekatan umum untuk mendeklarasikan ControlTemplate
adalah sebagai sumber daya dalam kamus sumber daya. Karena templat kontrol adalah sumber daya, templat tersebut mematuhi aturan cakupan yang sama yang berlaku untuk semua sumber daya. Misalnya, jika Anda mendeklarasikan templat kontrol di elemen akar file XAML definisi aplikasi Anda, templat dapat digunakan di mana saja dalam aplikasi Anda. Jika Anda menentukan templat di halaman, hanya halaman tersebut yang dapat menggunakan templat kontrol. Untuk informasi selengkapnya tentang sumber daya, lihat Xamarin.Forms Kamus Sumber Daya.
Contoh XAML berikut menunjukkan ControlTemplate
untuk CardView
objek:
<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
Ketika dinyatakan sebagai sumber daya, itu harus memiliki kunci yang ditentukan dengan x:Key
atribut sehingga dapat diidentifikasi dalam kamus sumber daya. Dalam contoh ini, elemen akar adalah CardViewControlTemplate
Frame
objek. Objek Frame
menggunakan ekstensi markup untuk mengaturnya BindingContext
ke instans RelativeSource
objek runtime tempat templat akan diterapkan, yang dikenal sebagai induk yang di-template. Objek Frame
menggunakan kombinasi Grid
objek , , Frame
Image
, Label
, dan BoxView
untuk menentukan struktur CardView
visual objek. Ekspresi pengikatan objek ini diselesaikan terhadap CardView
properti, karena mewarisi BindingContext
dari elemen akar Frame
. Untuk informasi selengkapnya tentang RelativeSource
ekstensi markup, lihat Xamarin.Forms Pengikatan Relatif.
Mengonsumsi ControlTemplate
ControlTemplate
Dapat diterapkan ke ContentView
kontrol kustom turunan dengan mengatur propertinya ControlTemplate
ke objek templat kontrol. Demikian pula, ControlTemplate
dapat diterapkan ke ContentPage
halaman turunan dengan mengatur propertinya ControlTemplate
ke objek templat kontrol. Pada runtime, saat ControlTemplate
diterapkan, semua kontrol yang ditentukan dalam ControlTemplate
ditambahkan ke pohon visual kontrol kustom yang di-templat, atau halaman templat.
Contoh berikut menunjukkan yang CardViewControlTemplate
ditetapkan ke ControlTemplate
properti setiap CardView
objek:
<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>
Dalam contoh ini, kontrol dalam CardViewControlTemplate
menjadi bagian dari pohon visual untuk setiap CardView
objek. Karena objek akar Frame
untuk templat kontrol mengaturnya BindingContext
ke induk yang di-template, Frame
dan anak-anaknya menyelesaikan ekspresi pengikatannya terhadap properti setiap CardView
objek.
Cuplikan layar berikut menunjukkan yang CardViewControlTemplate
diterapkan ke tiga CardView
objek:
Penting
Titik waktu yang ControlTemplate
diterapkan ke instans kontrol dapat dideteksi dengan mengambil alih OnApplyTemplate
metode dalam kontrol kustom templat, atau halaman templat. Untuk informasi selengkapnya, lihat Mendapatkan elemen bernama dari templat.
Meneruskan parameter dengan TemplateBinding
Ekstensi TemplateBinding
markup mengikat properti elemen yang berada di ControlTemplate
properti publik yang ditentukan oleh kontrol kustom templat atau halaman templat. Saat Anda menggunakan TemplateBinding
, Anda mengaktifkan properti pada kontrol untuk bertindak sebagai parameter ke templat. Oleh karena itu, ketika properti pada kontrol kustom templat atau halaman templat diatur, nilai tersebut diteruskan ke elemen yang memilikinya TemplateBinding
.
Penting
TemplateBinding
Ekspresi markup memungkinkan pengikatan RelativeSource
dari templat kontrol sebelumnya dihapus, dan mengganti Binding
ekspresi.
TemplateBinding
Ekstensi markup menentukan properti berikut:
Path
, dari jenisstring
, jalur ke properti .Mode
, dari jenisBindingMode
, arah di mana perubahan menyebar antara sumber dan target.Converter
, dari jenisIValueConverter
, pengonversi nilai pengikatan.ConverterParameter
, dari jenisobject
, parameter ke pengonversi nilai pengikatan.StringFormat
, dari jenisstring
, format string untuk pengikatan.
ContentProperty
Untuk TemplateBinding
ekstensi markup adalah Path
. Oleh karena itu, bagian "Path=" dari ekstensi markup dapat dihilangkan jika jalur adalah item pertama dalam TemplateBinding
ekspresi. Untuk informasi selengkapnya tentang menggunakan properti ini dalam ekspresi pengikatan, lihat Xamarin.Forms Pengikatan Data.
Peringatan
Ekstensi TemplateBinding
markup hanya boleh digunakan dalam ControlTemplate
. Namun, mencoba menggunakan TemplateBinding
ekspresi di luar ControlTemplate
tidak akan mengakibatkan kesalahan build atau pengecualian dilemparkan.
Contoh XAML berikut menunjukkan ControlTemplate
untuk CardView
objek, yang menggunakan TemplateBinding
ekstensi markup:
<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>
Dalam contoh ini, TemplateBinding
ekstensi markup menyelesaikan ekspresi pengikatan terhadap properti setiap CardView
objek. Cuplikan layar berikut menunjukkan yang CardViewControlTemplate
diterapkan ke tiga CardView
objek:
Penting
TemplateBinding
Menggunakan ekstensi markup setara dengan mengatur BindingContext
elemen akar dalam templat ke induk templatnya dengan RelativeSource
ekstensi markup, lalu menyelesaikan pengikatan objek anak dengan Binding
ekstensi markup. Bahkan, TemplateBinding
ekstensi markup membuat yang Binding
Source
adalah RelativeBindingSource.TemplatedParent
.
Menerapkan ControlTemplate dengan gaya
Templat kontrol juga dapat diterapkan dengan gaya. Ini dicapai dengan membuat gaya implisitControlTemplate
atau eksplisit yang menggunakan .
Contoh XAML berikut menunjukkan gaya implisitCardViewControlTemplate
yang menggunakan :
<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>
Dalam contoh ini, implisitStyle
secara otomatis diterapkan ke setiap CardView
objek, dan mengatur ControlTemplate
properti masing-masing CardView
ke CardViewControlTemplate
.
Untuk informasi selengkapnya tentang gaya, lihat Xamarin.Forms Gaya.
Menenangkan ulang UI kontrol
Ketika dibuat dan ditetapkan ke ControlTemplate
properti kontrol kustom turunanContentView
, atau ContentPage
halaman turunan, struktur visual yang ControlTemplate
ditentukan untuk kontrol atau halaman kustom diganti dengan struktur visual yang ditentukan dalam ControlTemplate
.
Misalnya, CardViewUI
kontrol kustom menentukan antarmuka penggunanya menggunakan XAML berikut:
<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>
Namun, kontrol yang terdiri dari UI ini dapat diganti dengan menentukan struktur visual baru dalam ControlTemplate
, dan menetapkannya ke ControlTemplate
properti CardViewUI
objek:
<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>
Dalam contoh ini, struktur CardViewUI
visual objek didefinisikan ulang dalam ControlTemplate
yang menyediakan struktur visual yang lebih ringkas yang cocok untuk daftar ringkas:
Mengganti konten menjadi ContentPresenter
ContentPresenter
Dapat ditempatkan dalam templat kontrol untuk menandai tempat konten ditampilkan oleh kontrol kustom templat atau halaman templat akan muncul. Kontrol kustom atau halaman yang menggunakan templat kontrol kemudian akan menentukan konten yang akan ditampilkan oleh ContentPresenter
. Diagram berikut mengilustrasikan ControlTemplate
untuk halaman yang berisi sejumlah kontrol, termasuk yang ContentPresenter
ditandai dengan persegi panjang biru:
XAML berikut menunjukkan templat kontrol bernama TealTemplate
yang berisi ContentPresenter
dalam struktur visualnya:
<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>
Contoh berikut menunjukkan TealTemplate
ditetapkan ke ControlTemplate
properti halaman turunan ContentPage
:
<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>
Pada runtime, ketika TealTemplate
diterapkan ke halaman, konten halaman diganti ke dalam yang ContentPresenter
ditentukan dalam templat kontrol:
Mendapatkan elemen bernama dari templat
Elemen bernama dalam templat kontrol dapat diambil dari kontrol kustom templat atau halaman templat. Ini dapat dicapai dengan GetTemplateChild
metode , yang mengembalikan elemen bernama di pohon visual yang dibuat ControlTemplate
, jika ditemukan. Jika tidak, ia kembali null
.
Setelah templat kontrol dibuat, metode templat OnApplyTemplate
dipanggil. Oleh karena itu GetTemplateChild
, metode harus dipanggil dari OnApplyTemplate
penimpaan di halaman kontrol templat atau templat.
Penting
Metode GetTemplateChild
ini hanya boleh dipanggil setelah OnApplyTemplate
metode dipanggil.
XAML berikut menunjukkan templat kontrol bernama TealTemplate
yang dapat diterapkan ke ContentPage
halaman turunan:
<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>
Dalam contoh ini, Label
elemen diberi nama, dan dapat diambil dalam kode untuk halaman templat. Ini dicapai dengan memanggil GetTemplateChild
metode dari OnApplyTemplate
penimpaan untuk halaman templat:
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";
}
}
Dalam contoh ini, Label
objek bernama changeThemeLabel
diambil setelah ControlTemplate
telah diinstansiasi. changeThemeLabel
kemudian dapat diakses dan dimanipulasi oleh AccessTemplateElementPage
kelas . Cuplikan layar berikut menunjukkan bahwa teks yang Label
ditampilkan oleh telah diubah:
Ikat ke viewmodel
ControlTemplate
dapat mengikat data ke viewmodel, bahkan ketika ControlTemplate
pengikatan ke induk templat (instans objek runtime tempat templat diterapkan).
Contoh XAML berikut menunjukkan halaman yang menggunakan viewmodel bernama 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>
Dalam contoh ini, BindingContext
halaman diatur ke PeopleViewModel
instans. Viewmodel ini mengekspos People
koleksi dan bernama ICommand
DeletePersonCommand
. StackLayout
Pada halaman menggunakan tata letak yang dapat diikat ke pengikatan data ke People
koleksi, dan ItemTemplate
tata letak yang dapat diikat diatur ke PersonTemplate
sumber daya. Ini DataTemplate
menentukan bahwa setiap item dalam People
koleksi akan ditampilkan menggunakan CardView
objek. Struktur CardView
visual objek didefinisikan menggunakan bernama 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>
Dalam contoh ini, elemen akar adalah ControlTemplate
Frame
objek. Objek Frame
menggunakan RelativeSource
ekstensi markup untuk mengaturnya BindingContext
ke induk templat. Ekspresi Frame
pengikatan objek dan anak-anaknya mengatasi CardView
properti, karena mewarisi BindingContext
dari elemen akar Frame
. Cuplikan layar berikut menunjukkan halaman yang menampilkan People
koleksi, yang terdiri dari tiga item:
Saat objek dalam ikatan ControlTemplate
ke properti pada induk templatnya, Button
dalam templat kontrol mengikat ke induk templatnya, dan ke DeletePersonCommand
di viewmodel. Ini karena Button.Command
properti mendefinisikan ulang sumber pengikatannya menjadi konteks pengikatan leluhur yang jenis konteks pengikatannya adalah PeopleViewModel
, yang merupakan StackLayout
. Bagian Path
dari ekspresi pengikatan kemudian dapat menyelesaikan DeletePersonCommand
properti . Namun, Button.CommandParameter
properti tidak mengubah sumber pengikatannya, sebagai gantinya mewarisinya dari induknya di ControlTemplate
. Oleh karena itu, CommandParameter
properti mengikat properti CardTitle
dari CardView
.
Efek keseluruhan dari Button
pengikatan adalah bahwa ketika Button
diketuk, DeletePersonCommand
di PeopleViewModel
kelas dijalankan, dengan nilai CardName
properti diteruskan ke DeletePersonCommand
. Ini menghasilkan yang ditentukan CardView
dihapus dari tata letak yang dapat diikat:
Untuk informasi selengkapnya tentang pengikatan relatif, lihat Xamarin.Forms Pengikatan Relatif.