2. část: Základní syntaxe XAML

XAML je většinou navržený pro vytváření instancí a inicializaci objektů. Často však musí být vlastnosti nastaveny na složité objekty, které nelze snadno reprezentovat jako řetězce XML, a někdy vlastnosti definované jednou třídou musí být nastaveny v podřízené třídě. Tyto dva požadavky vyžadují základní funkce syntaxe XAML elementů vlastností a připojených vlastností.

Elementy vlastností

V jazyce XAML jsou vlastnosti tříd obvykle nastaveny jako atributy XML:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large"
       TextColor="Aqua" />

Existuje však alternativní způsob, jak nastavit vlastnost v XAML. Pokud chcete vyzkoušet tuto alternativu TextColor, odstraňte nejprve existující TextColor nastavení:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large" />

Otevřete značku prázdného elementu Label tak, že ji oddělíte na počáteční a koncové značky:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">

</Label>

Do těchto značek přidejte počáteční a koncové značky, které se skládají z názvu třídy a názvu vlastnosti oddělené tečkou:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">
    <Label.TextColor>

    </Label.TextColor>
</Label>

Nastavte hodnotu vlastnosti jako obsah těchto nových značek, například takto:

<Label Text="Hello, XAML!"
       VerticalOptions="Center"
       FontAttributes="Bold"
       FontSize="Large">
    <Label.TextColor>
        Aqua
    </Label.TextColor>
</Label>

Tyto dva způsoby, jak zadat TextColor vlastnost, jsou funkčně ekvivalentní, ale nepoužívejte dva způsoby pro stejnou vlastnost, protože by efektivně nastavovala vlastnost dvakrát a může být nejednoznačná.

S touto novou syntaxí je možné zavést určitou praktickou terminologii:

  • Label je objektový prvek. Jedná se o objekt vyjádřený Xamarin.Forms jako element XML.
  • Text, VerticalOptionsFontAttributes a FontSize jsou atributy vlastností. Jsou to Xamarin.Forms vlastnosti vyjádřené jako atributy XML.
  • V tomto posledním fragmentu kódu TextColor se stal elementem vlastnosti. Jedná se o Xamarin.Forms vlastnost, ale nyní se jedná o element XML.

Definice elementů vlastností se zpočátku může zdát porušení syntaxe XML, ale není to. Tečka nemá v XML žádný zvláštní význam. Dekodér Label.TextColor XML je jednoduše normální podřízený prvek.

V jazyce XAML je ale tato syntaxe velmi zvláštní. Jedním z pravidel pro prvky vlastnosti je, že se ve značce nemůže objevit nic jiného Label.TextColor . Hodnota vlastnosti je vždy definována jako obsah mezi počáteční a koncové značky prvku property.

Syntaxi elementu vlastnosti můžete použít u více než jedné vlastnosti:

<Label Text="Hello, XAML!"
       VerticalOptions="Center">
    <Label.FontAttributes>
        Bold
    </Label.FontAttributes>
    <Label.FontSize>
        Large
    </Label.FontSize>
    <Label.TextColor>
        Aqua
    </Label.TextColor>
</Label>

Nebo můžete použít syntaxi elementu property pro všechny vlastnosti:

<Label>
    <Label.Text>
        Hello, XAML!
    </Label.Text>
    <Label.FontAttributes>
        Bold
    </Label.FontAttributes>
    <Label.FontSize>
        Large
    </Label.FontSize>
    <Label.TextColor>
        Aqua
    </Label.TextColor>
    <Label.VerticalOptions>
        Center
    </Label.VerticalOptions>
</Label>

Syntaxe elementu vlastností se zpočátku může zdát jako nepotřebná dlouho vinutá náhrada za něco poměrně jednoduchého a v těchto příkladech, která je jistě případem.

Syntaxe elementu property se však stává zásadní, pokud je hodnota vlastnosti příliš složitá, aby byla vyjádřena jako jednoduchý řetězec. V rámci značek elementů vlastností můžete vytvořit instanci jiného objektu a nastavit jeho vlastnosti. Vlastnost můžete například explicitně nastavit VerticalOptions na LayoutOptions hodnotu s nastavením vlastnosti:

<Label>
    ...
    <Label.VerticalOptions>
        <LayoutOptions Alignment="Center" />
    </Label.VerticalOptions>
</Label>

Další příklad: Má Grid dvě vlastnosti pojmenované RowDefinitions a ColumnDefinitions. Tyto dvě vlastnosti jsou typu RowDefinitionCollection a ColumnDefinitionCollectionkteré jsou kolekcemi RowDefinition a ColumnDefinition objekty. K nastavení těchto kolekcí je potřeba použít syntaxi elementu vlastnosti.

Tady je začátek souboru XAML pro GridDemoPage třídu, který zobrazuje značky elementů vlastností pro kolekce RowDefinitions a ColumnDefinitions kolekce:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>
        ...
    </Grid>
</ContentPage>

Všimněte si zkrácené syntaxe pro definování buněk s automatickou velikostí, buněk s pixelovými šířkami a výškami a nastavením hvězdičky.

Přidružené vlastnosti

Právě jste viděli, že Grid požadované prvky vlastností a RowDefinitionsColumnDefinitions kolekce definují řádky a sloupce. Pro programátora ale také musí existovat nějaký způsob, jak označit řádek a sloupec, kde se nachází každá podřízená položka Grid .

V rámci značky pro každé podřízené položky Grid zadáte řádek a sloupec tohoto podřízeného atributu pomocí následujících atributů:

  • Grid.Row
  • Grid.Column

Výchozí hodnoty těchto atributů jsou 0. Můžete také určit, jestli podřízená položka zahrnuje více než jeden řádek nebo sloupec s těmito atributy:

  • Grid.RowSpan
  • Grid.ColumnSpan

Tyto dva atributy mají výchozí hodnoty 1.

Tady je kompletní soubor GridDemoPage.xaml:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.GridDemoPage"
             Title="Grid Demo Page">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>

        <Label Text="Autosized cell"
               Grid.Row="0" Grid.Column="0"
               TextColor="White"
               BackgroundColor="Blue" />

        <BoxView Color="Silver"
                 HeightRequest="0"
                 Grid.Row="0" Grid.Column="1" />

        <BoxView Color="Teal"
                 Grid.Row="1" Grid.Column="0" />

        <Label Text="Leftover space"
               Grid.Row="1" Grid.Column="1"
               TextColor="Purple"
               BackgroundColor="Aqua"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Span two rows (or more if you want)"
               Grid.Row="0" Grid.Column="2" Grid.RowSpan="2"
               TextColor="Yellow"
               BackgroundColor="Blue"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Span two columns"
               Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2"
               TextColor="Blue"
               BackgroundColor="Yellow"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

        <Label Text="Fixed 100x100"
               Grid.Row="2" Grid.Column="2"
               TextColor="Aqua"
               BackgroundColor="Red"
               HorizontalTextAlignment="Center"
               VerticalTextAlignment="Center" />

    </Grid>
</ContentPage>

Grid.Row 0 a Grid.Column nastavení 0 nejsou povinné, ale jsou obecně zahrnuty pro účely přehlednosti.

Vypadá takto:

Rozložení mřížky

Judging výhradně ze syntaxe, tyto , , a atributy se zdá být statické pole nebo vlastnosti Grid, ale zajímavé dostatečně, Grid nedefinuje nic pojmenovaného Row, Column, RowSpan, nebo ColumnSpan.Grid.ColumnSpanGrid.RowSpanGrid.ColumnGrid.Row

Grid Místo toho definuje čtyři vlastnosti s možností vytvoření vazby s názvem RowProperty, ColumnProperty, RowSpanPropertya ColumnSpanProperty. Jedná se o speciální typy vazebných vlastností označovaných jako připojené vlastnosti. Jsou definovány Grid třídou, ale nastaveny na podřízené Gridpoložky .

Pokud chcete tyto připojené vlastnosti použít v kódu, Grid třída poskytuje statické metody s názvem SetRow, GetColumna tak dále. V jazyce XAML jsou však tyto připojené vlastnosti nastaveny jako atributy v podřízených objektech pomocí jednoduchých Grid názvů vlastností.

Připojené vlastnosti jsou vždy rozpoznatelné v souborech XAML jako atributy obsahující třídu i název vlastnosti oddělené tečkou. Nazývají se připojené vlastnosti , protože jsou definovány jednou třídou (v tomto případě Grid), ale připojeny k jiným objektům (v tomto případě podřízené položky Grid). Během rozložení může interrogovat hodnoty těchto připojených vlastností, abyste věděli, Grid kam umístit jednotlivé podřízené objekty.

Třída AbsoluteLayout definuje dvě připojené vlastnosti pojmenované LayoutBounds a LayoutFlags. Zde je model kontrolní desky realizované pomocí proporcionálního umístění a určení velikosti funkcí AbsoluteLayout:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.AbsoluteDemoPage"
             Title="Absolute Demo Page">

    <AbsoluteLayout BackgroundColor="#FF8080">
        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.33, 0, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="1, 0, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0, 0.33, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.67, 0.33, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.33, 0.67, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="1, 0.67, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0, 1, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

        <BoxView Color="#8080FF"
                 AbsoluteLayout.LayoutBounds="0.67, 1, 0.25, 0.25"
                 AbsoluteLayout.LayoutFlags="All" />

  </AbsoluteLayout>
</ContentPage>

A tady je:

Absolutní rozložení

Pro něco takového byste mohli položit otázku moudrosti použití XAML. Jistě, opakování a správnost obdélníku LayoutBounds naznačuje, že by mohlo být lépe realizováno v kódu.

To je jistě legitimní obava a není problém s vyvážením použití kódu a značek při definování uživatelských rozhraní. Je snadné definovat některé vizuály v JAZYCE XAML a pak pomocí konstruktoru souboru kódu přidat další vizuály, které můžou být lépe generovány ve smyčce.

Vlastnosti obsahu

V předchozích příkladech jsou objekty a objekty Gridnastaveny na Content vlastnost ContentPage, a podřízené položky těchto rozložení jsou ve skutečnosti položky v kolekciChildren.AbsoluteLayoutStackLayout Content Tyto vlastnosti Children ale nejsou nikde v souboru XAML.

Určitě můžete zahrnout vlastnosti a Children vlastnosti jako elementy Content vlastností, například v ukázce XamlPlusCode:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <ContentPage.Content>
        <StackLayout>
            <StackLayout.Children>
                <Slider VerticalOptions="CenterAndExpand"
                        ValueChanged="OnSliderValueChanged" />

                <Label x:Name="valueLabel"
                       Text="A simple Label"
                       FontSize="Large"
                       HorizontalOptions="Center"
                       VerticalOptions="CenterAndExpand" />

                <Button Text="Click Me!"
                      HorizontalOptions="Center"
                      VerticalOptions="CenterAndExpand"
                      Clicked="OnButtonClicked" />
            </StackLayout.Children>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

Skutečnou otázkou je: Proč nejsou tyto elementy vlastností v souboru XAML povinné?

Elementy definované Xamarin.Forms pro použití v XAML mohou mít jednu vlastnost označenou v ContentProperty atributu třídy. Pokud třídu vyhledáte ContentPage v online Xamarin.Forms dokumentaci, uvidíte tento atribut:

[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage

To znamená, že značky elementu Content property nejsou povinné. Předpokládá se, že se k vlastnosti přiřadí veškerý obsah XML, který se zobrazí mezi počáteční a koncovou ContentPage značkou Content .

StackLayout, Grid, AbsoluteLayouta RelativeLayout všechny odvozeny od Layout<View>, a pokud hledáte Layout<T> v Xamarin.Forms dokumentaci, uvidíte další ContentProperty atribut:

[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout ...

To umožňuje automatické přidání obsahu rozložení do Children kolekce bez explicitních Children značek elementů vlastností.

Jiné třídy mají ContentProperty také definice atributů. Například vlastnost Label obsahu je Text. Projděte si dokumentaci k rozhraní API pro ostatní.

Rozdíly mezi platformami s onPlatformem

V jednostrákových aplikacích je běžné nastavit Padding vlastnost na stránce, aby se zabránilo přepsání stavového řádku iOS. V kódu můžete vlastnost použít k tomuto účelu Device.RuntimePlatform :

if (Device.RuntimePlatform == Device.iOS)
{
    Padding = new Thickness(0, 20, 0, 0);
}

V XAML můžete také provádět něco podobného OnPlatform pomocí a On tříd. Nejprve zahrňte elementy vlastnosti pro Padding vlastnost v horní části stránky:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>

    </ContentPage.Padding>
    ...
</ContentPage>

Do těchto značek zahrňte značku OnPlatform . OnPlatform je obecná třída. V tomto případě je třeba zadat argument obecného typu, Thicknesscož je typ Padding vlastnosti. Naštěstí existuje atribut XAML speciálně pro definování obecných argumentů volaný x:TypeArguments. Mělo by se shodovat s typem vlastnosti, kterou nastavujete:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">

        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

OnPlatform má vlastnost s názvem Platforms , která je objekty IListOn . Pro tuto vlastnost použijte značky elementů vlastností:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.Platforms>

            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Teď přidejte On prvky. Pro každou z nich nastavte Platform vlastnost a Value vlastnost na revize vlastnosti Thickness :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <OnPlatform.Platforms>
                <On Platform="iOS" Value="0, 20, 0, 0" />
                <On Platform="Android" Value="0, 0, 0, 0" />
                <On Platform="UWP" Value="0, 0, 0, 0" />
            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Tento kód lze zjednodušit. Vlastnost obsahu OnPlatform je Platforms, takže tyto značky elementů vlastností lze odebrat:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
            <On Platform="Android" Value="0, 0, 0, 0" />
            <On Platform="UWP" Value="0, 0, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Vlastnost PlatformOn je typu IList<string>, takže můžete zahrnout více platforem, pokud jsou hodnoty stejné:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
            <On Platform="Android, UWP" Value="0, 0, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Vzhledem k tomu, že Android a UPW jsou nastaveny na výchozí hodnotu Padding, lze tuto značku odebrat:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0, 20, 0, 0" />
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Toto je standardní způsob nastavení vlastnosti závislé Padding na platformě v JAZYCE XAML. Value Pokud nastavení nemůže být reprezentováno jedním řetězcem, můžete pro něj definovat prvky vlastností:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="...">

    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS">
                <On.Value>
                    0, 20, 0, 0
                </On.Value>
            </On>
        </OnPlatform>
    </ContentPage.Padding>
  ...
</ContentPage>

Poznámka:

Rozšíření OnPlatform značek lze také použít v JAZYCE XAML k přizpůsobení vzhledu uživatelského rozhraní na základě jednotlivých platforem. Poskytuje stejné funkce jako OnPlatform třídy a On poskytuje stručnější reprezentaci. Další informace naleznete v tématu OnPlatform Markup Extension.

Shrnutí

U elementů vlastností a připojených vlastností byla vytvořena většina základní syntaxe XAML. Někdy ale potřebujete nastavit vlastnosti na objekty nepřímým způsobem, například ze slovníku prostředků. Tento přístup je popsaný v další části, část 3. Rozšíření značek XAML