Xamarin.Forms šablony ovládacích prvků

Download Sample Stažení ukázky

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 CardViewControlTemplateFrame . 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, , ImageFrame, Labela 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:

Screenshots of templated CardView objects, on iOS and Android

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 TemplateBindingpří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, typu string, cesta k vlastnosti.
  • Mode, typu BindingMode, směr, ve kterém se změny šíří mezi zdrojem a cílem.
  • Converter, typu IValueConverter, převaděč hodnoty vazby.
  • ConverterParameter, typu object, parametr pro převaděč hodnoty vazby.
  • StringFormat, typu string, 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:

Screenshots of templated CardView objects

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 ControlTemplatea 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:

Screenshots of templated CardViewUI objects, on iOS and Android

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:

Control Template for a ContentPage

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:

Screenshots of templated page object, on iOS and Android

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 :

Screenshots of templated page object

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 ICommandDeletePersonCommand. 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é ControlTemplateCardViewControlTemplate:

<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 ControlTemplateFrame . 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:

Screenshots of three templated CardView objects

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í, ButtonDeletePersonCommand 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:

Screenshots of two templated CardView objects

Další informace o relativních vazbách naleznete v tématu Xamarin.Forms Relativní vazby.