Udostępnij za pośrednictwem


Część 3. Rozszerzenia struktury znaczników XAML

Rozszerzenia znaczników XAML stanowią ważną funkcję w języku XAML, która umożliwia ustawianie właściwości na obiekty lub wartości, do których odwołuje się pośrednio z innych źródeł. Rozszerzenia znaczników XAML są szczególnie ważne w przypadku udostępniania obiektów i odwoływania się do stałych używanych w całej aplikacji, ale znajdują swoje największe narzędzie w powiązaniach danych.

Rozszerzenia struktury znaczników XAML

Ogólnie rzecz biorąc, język XAML służy do ustawiania właściwości obiektu na jawne wartości, takie jak ciąg, liczba, składowa wyliczenia lub ciąg, który jest konwertowany na wartość w tle.

Czasami jednak właściwości muszą odwoływać się do wartości zdefiniowanych w innym miejscu lub które mogą wymagać nieco przetwarzania przez kod w czasie wykonywania. W tych celach dostępne są rozszerzenia znaczników XAML.

Te rozszerzenia znaczników XAML nie są rozszerzeniami xml. XAML jest całkowicie legalny kod XML. Są one nazywane "rozszerzeniami", ponieważ są one wspierane przez kod w klasach, które implementują IMarkupExtension. Możesz napisać własne niestandardowe rozszerzenia znaczników.

W wielu przypadkach rozszerzenia znaczników XAML są natychmiast rozpoznawalne w plikach XAML, ponieważ są one wyświetlane jako ustawienia atrybutów rozdzielane nawiasami klamrowymi: { i }, ale czasami rozszerzenia znaczników pojawiają się w znacznikach jako konwencjonalne elementy.

Współdzielone zasoby

Niektóre strony XAML zawierają kilka widoków z właściwościami ustawionymi na te same wartości. Na przykład wiele ustawień właściwości dla tych Button obiektów jest takich samych:

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

    <StackLayout>
        <Button Text="Do this!"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                BorderWidth="3"
                Rotation="-15"
                TextColor="Red"
                FontSize="24" />

        <Button Text="Do that!"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                BorderWidth="3"
                Rotation="-15"
                TextColor="Red"
                FontSize="24" />

        <Button Text="Do the other thing!"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                BorderWidth="3"
                Rotation="-15"
                TextColor="Red"
                FontSize="24" />

    </StackLayout>
</ContentPage>

Jeśli należy zmienić jedną z tych właściwości, możesz wolisz wprowadzić zmianę tylko raz, a nie trzy razy. Gdyby był to kod, prawdopodobnie będziesz używać stałych i statycznych obiektów tylko do odczytu, aby zachować takie wartości spójne i łatwe do zmodyfikowania.

W języku XAML jednym z popularnych rozwiązań jest przechowywanie takich wartości lub obiektów w słowniku zasobów. Klasa VisualElement definiuje właściwość o nazwie Resources typu ResourceDictionary, która jest słownikiem z kluczami typu string i wartości typu object. Można umieścić obiekty w tym słowniku, a następnie odwołać się do nich z znaczników, wszystkie w języku XAML.

Aby użyć słownika zasobów na stronie, dołącz parę tagów Resources property-element. Najwygodniejsze jest umieszczenie ich w górnej części strony:

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

    <ContentPage.Resources>

    </ContentPage.Resources>
    ...
</ContentPage>

Należy również jawnie uwzględnić ResourceDictionary tagi:

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

    <ContentPage.Resources>
        <ResourceDictionary>

        </ResourceDictionary>
    </ContentPage.Resources>
    ...
</ContentPage>

Teraz do słownika zasobów można dodawać obiekty i wartości różnych typów. Te typy muszą być tworzone wystąpienia. Nie mogą być na przykład klas abstrakcyjnych. Te typy muszą również mieć publiczny konstruktor bez parametrów. Każdy element wymaga klucza słownika określonego za pomocą atrybutu x:Key . Na przykład:

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

    <ContentPage.Resources>
        <ResourceDictionary>
            <LayoutOptions x:Key="horzOptions"
                           Alignment="Center" />

            <LayoutOptions x:Key="vertOptions"
                           Alignment="Center"
                           Expands="True" />
        </ResourceDictionary>
    </ContentPage.Resources>
    ...
</ContentPage>

Te dwa elementy są wartościami typu LayoutOptionsstruktury , a każdy z nich ma unikatowy klucz i jeden lub dwa zestaw właściwości. W kodzie i narzucie jest znacznie częściej używane statyczne pola LayoutOptions, ale w tym miejscu bardziej wygodne jest ustawienie właściwości.

Teraz należy ustawić HorizontalOptions właściwości i VerticalOptions tych przycisków na te zasoby, a to zrobić za pomocą StaticResource rozszerzenia znaczników XAML:

<Button Text="Do this!"
        HorizontalOptions="{StaticResource horzOptions}"
        VerticalOptions="{StaticResource vertOptions}"
        BorderWidth="3"
        Rotation="-15"
        TextColor="Red"
        FontSize="24" />

StaticResource Rozszerzenie znaczników jest zawsze rozdzielane nawiasami klamrowymi i zawiera klucz słownika.

Nazwa StaticResource odróżnia ją od DynamicResourceelementu , który Xamarin.Forms również obsługuje. DynamicResource jest przeznaczony dla kluczy słownika skojarzonych z wartościami, które mogą ulec zmianie podczas wykonywania, podczas gdy StaticResource są tworzone elementy ze słownika tylko raz.

BorderWidth Dla właściwości należy przechowywać dwukrotnie w słowniku. Język XAML wygodnie definiuje tagi dla typowych typów danych, takich jak x:Double i x:Int32:

<ContentPage.Resources>
    <ResourceDictionary>
        <LayoutOptions x:Key="horzOptions"
                       Alignment="Center" />

        <LayoutOptions x:Key="vertOptions"
                       Alignment="Center"
                       Expands="True" />

        <x:Double x:Key="borderWidth">
            3
        </x:Double>
    </ResourceDictionary>
</ContentPage.Resources>

Nie musisz umieszczać go w trzech wierszach. Ten wpis słownika dla tego kąta obrotu zajmuje tylko jeden wiersz:

<ContentPage.Resources>
    <ResourceDictionary>
        <LayoutOptions x:Key="horzOptions"
                       Alignment="Center" />

        <LayoutOptions x:Key="vertOptions"
                       Alignment="Center"
                       Expands="True" />

         <x:Double x:Key="borderWidth">
            3
         </x:Double>

        <x:Double x:Key="rotationAngle">-15</x:Double>
    </ResourceDictionary>
</ContentPage.Resources>

Te dwa zasoby można odwoływać się w taki sam sposób jak wartości LayoutOptions :

<Button Text="Do this!"
        HorizontalOptions="{StaticResource horzOptions}"
        VerticalOptions="{StaticResource vertOptions}"
        BorderWidth="{StaticResource borderWidth}"
        Rotation="{StaticResource rotationAngle}"
        TextColor="Red"
        FontSize="24" />

W przypadku zasobów typu Colormożna użyć tych samych reprezentacji ciągów, które są używane podczas bezpośredniego przypisywania atrybutów tych typów. Konwertery typów są wywoływane podczas tworzenia zasobu. Oto zasób typu Color:

<Color x:Key="textColor">Red</Color>

Często programy ustawiają FontSize właściwość na element członkowski NamedSize wyliczenia, na przykład Large. Klasa FontSizeConverter działa za kulisami, aby przekonwertować ją na wartość zależną od platformy przy użyciu Device.GetNamedSized metody . Jednak podczas definiowania zasobu rozmiaru czcionki warto użyć wartości liczbowej, jak pokazano tutaj jako x:Double typ:

<x:Double x:Key="fontSize">24</x:Double>

Teraz wszystkie właściwości z wyjątkiem Text są definiowane przez ustawienia zasobów:

<Button Text="Do this!"
        HorizontalOptions="{StaticResource horzOptions}"
        VerticalOptions="{StaticResource vertOptions}"
        BorderWidth="{StaticResource borderWidth}"
        Rotation="{StaticResource rotationAngle}"
        TextColor="{StaticResource textColor}"
        FontSize="{StaticResource fontSize}" />

Istnieje również możliwość użycia OnPlatform w słowniku zasobów w celu zdefiniowania różnych wartości dla platform. Oto jak OnPlatform obiekt może być częścią słownika zasobów dla różnych kolorów tekstu:

<OnPlatform x:Key="textColor"
            x:TypeArguments="Color">
    <On Platform="iOS" Value="Red" />
    <On Platform="Android" Value="Aqua" />
    <On Platform="UWP" Value="#80FF80" />
</OnPlatform>

Zwróć uwagę, że OnPlatform zarówno atrybut, x:Key ponieważ jest to obiekt w słowniku, jak i x:TypeArguments atrybut, ponieważ jest to klasa ogólna. Atrybuty iOS, Androidi UWP są konwertowane na Color wartości podczas inicjowania obiektu.

Oto końcowy kompletny plik XAML z trzema przyciskami, które uzyskują dostęp do sześciu wartości udostępnionych:

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

    <ContentPage.Resources>
        <ResourceDictionary>
            <LayoutOptions x:Key="horzOptions"
                           Alignment="Center" />

            <LayoutOptions x:Key="vertOptions"
                           Alignment="Center"
                           Expands="True" />

            <x:Double x:Key="borderWidth">3</x:Double>

            <x:Double x:Key="rotationAngle">-15</x:Double>

            <OnPlatform x:Key="textColor"
                        x:TypeArguments="Color">
                <On Platform="iOS" Value="Red" />
                <On Platform="Android" Value="Aqua" />
                <On Platform="UWP" Value="#80FF80" />
            </OnPlatform>

            <x:Double x:Key="fontSize">24</x:Double>
        </ResourceDictionary>
    </ContentPage.Resources>

    <StackLayout>
        <Button Text="Do this!"
                HorizontalOptions="{StaticResource horzOptions}"
                VerticalOptions="{StaticResource vertOptions}"
                BorderWidth="{StaticResource borderWidth}"
                Rotation="{StaticResource rotationAngle}"
                TextColor="{StaticResource textColor}"
                FontSize="{StaticResource fontSize}" />

        <Button Text="Do that!"
                HorizontalOptions="{StaticResource horzOptions}"
                VerticalOptions="{StaticResource vertOptions}"
                BorderWidth="{StaticResource borderWidth}"
                Rotation="{StaticResource rotationAngle}"
                TextColor="{StaticResource textColor}"
                FontSize="{StaticResource fontSize}" />

        <Button Text="Do the other thing!"
                HorizontalOptions="{StaticResource horzOptions}"
                VerticalOptions="{StaticResource vertOptions}"
                BorderWidth="{StaticResource borderWidth}"
                Rotation="{StaticResource rotationAngle}"
                TextColor="{StaticResource textColor}"
                FontSize="{StaticResource fontSize}" />

    </StackLayout>
</ContentPage>

Zrzuty ekranu weryfikują spójny styl i styl zależny od platformy:

Kontrolki stylizowane

Chociaż najbardziej typowe jest zdefiniowanie Resources kolekcji w górnej części strony, należy pamiętać, że Resources właściwość jest definiowana przez VisualElementelement , a kolekcje można mieć Resources na innych elementach na stronie. Na przykład spróbuj dodać jeden do elementu w tym przykładzie StackLayout :

<StackLayout>
    <StackLayout.Resources>
        <ResourceDictionary>
            <Color x:Key="textColor">Blue</Color>
        </ResourceDictionary>
    </StackLayout.Resources>
    ...
</StackLayout>

Dowiesz się, że kolor tekstu przycisków jest teraz niebieski. Zasadniczo za każdym razem, gdy analizator XAML napotka rozszerzenie znaczników, wyszukuje StaticResource drzewo wizualne i używa pierwszego ResourceDictionary napotkanego klucza.

Jednym z najpopularniejszych typów obiektów przechowywanych w słownikach zasobów jest Xamarin.FormsStyleelement , który definiuje kolekcję ustawień właściwości. Style zostały omówione w artykule Style.

Czasami deweloperzy nowi w języku XAML zastanawiają się, czy mogą umieścić element wizualny, taki jak Label lub Button w obiekcie ResourceDictionary. Chociaż z pewnością jest to możliwe, nie ma sensu. Celem obiektu ResourceDictionary jest udostępnianie obiektów. Nie można udostępnić elementu wizualizacji. To samo wystąpienie nie może być wyświetlane dwa razy na jednej stronie.

Rozszerzenie x:Static Markup

Pomimo podobieństw ich nazw x:Static i StaticResource są bardzo różne. StaticResource Zwraca obiekt ze słownika zasobów, gdy x:Static uzyskuje dostęp do jednego z następujących elementów:

  • publiczne pole statyczne
  • publiczna właściwość statyczna
  • pole stałej publicznej
  • element członkowski wyliczenia.

StaticResource Rozszerzenie znaczników jest obsługiwane przez implementacje XAML, które definiują słownik zasobów, podczas gdy x:Static jest wewnętrzną częścią XAML, jak x ujawnia prefiks.

Oto kilka przykładów, które pokazują, jak x:Static jawnie odwoływać się do pól statycznych i elementów członkowskich wyliczenia:

<Label Text="Hello, XAML!"
       VerticalOptions="{x:Static LayoutOptions.Start}"
       HorizontalTextAlignment="{x:Static TextAlignment.Center}"
       TextColor="{x:Static Color.Aqua}" />

Do tej pory nie jest to bardzo imponujące. x:Static Jednak rozszerzenie znaczników może również odwoływać się do pól statycznych lub właściwości z własnego kodu. Na przykład oto AppConstants klasa zawierająca niektóre pola statyczne, których można użyć na wielu stronach w całej aplikacji:

using System;
using Xamarin.Forms;

namespace XamlSamples
{
    static class AppConstants
    {
        public static readonly Thickness PagePadding;

        public static readonly Font TitleFont;

        public static readonly Color BackgroundColor = Color.Aqua;

        public static readonly Color ForegroundColor = Color.Brown;

        static AppConstants()
        {
            switch (Device.RuntimePlatform)
            {
                case Device.iOS:
                    PagePadding = new Thickness(5, 20, 5, 0);
                    TitleFont = Font.SystemFontOfSize(35, FontAttributes.Bold);
                    break;

                case Device.Android:
                    PagePadding = new Thickness(5, 0, 5, 0);
                    TitleFont = Font.SystemFontOfSize(40, FontAttributes.Bold);
                    break;

                case Device.UWP:
                    PagePadding = new Thickness(5, 0, 5, 0);
                    TitleFont = Font.SystemFontOfSize(50, FontAttributes.Bold);
                    break;
            }
        }
    }
}

Aby odwołać się do pól statycznych tej klasy w pliku XAML, musisz w jakiś sposób wskazać w pliku XAML, w którym znajduje się ten plik. Należy to zrobić za pomocą deklaracji przestrzeni nazw XML.

Pamiętaj, że pliki XAML utworzone w ramach standardowego Xamarin.Forms szablonu XAML zawierają dwie deklaracje przestrzeni nazw XML: jedną do uzyskiwania Xamarin.Forms dostępu do klas, a drugą do odwoływania się do tagów i atrybutów wewnętrznych języka XAML:

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

Aby uzyskać dostęp do innych klas, potrzebne będą dodatkowe deklaracje przestrzeni nazw XML. Każda dodatkowa deklaracja przestrzeni nazw XML definiuje nowy prefiks. Aby uzyskać dostęp do klas lokalnych w bibliotece .NET Standard aplikacji udostępnionej, takiej jak AppConstants, programiści XAML często używają prefiksu local. Deklaracja przestrzeni nazw musi wskazywać nazwę przestrzeni nazw CLR (środowisko uruchomieniowe języka wspólnego), znaną również jako nazwa przestrzeni nazw platformy .NET, która jest nazwą wyświetlaną w definicji języka C# namespace lub w using dyrektywie:

xmlns:local="clr-namespace:XamlSamples"

Można również zdefiniować deklaracje przestrzeni nazw XML dla przestrzeni nazw platformy .NET w dowolnym zestawie, do którego odwołuje się biblioteka .NET Standard. Na przykład poniżej sys przedstawiono prefiks dla standardowej przestrzeni nazw platformy .NET System , która znajduje się w zestawie netstandard . Ponieważ jest to inny zestaw, należy również określić nazwę zestawu, w tym przypadku netstandard:

xmlns:sys="clr-namespace:System;assembly=netstandard"

Zwróć uwagę, że słowo kluczowe clr-namespace następuje dwukropkiem, a następnie nazwa przestrzeni nazw platformy .NET, po którym następuje średnik, słowo kluczowe assembly, znak równości i nazwa zestawu.

Tak, dwukropek następuje clr-namespace , ale znak równości jest zgodny z assembly. Składnia została zdefiniowana w ten sposób celowo: większość deklaracji przestrzeni nazw XML odwołuje się do identyfikatora URI, który rozpoczyna nazwę schematu identyfikatora URI, na przykład http, po którym zawsze następuje dwukropek. Część clr-namespace tego ciągu ma naśladować tę konwencję.

Oba te deklaracje przestrzeni nazw są uwzględnione w przykładzie StaticConstantsPage . Zwróć uwagę, że BoxView wymiary są ustawione na Math.PI i Math.E, ale skalowane według współczynnika 100:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples"
             xmlns:sys="clr-namespace:System;assembly=netstandard"
             x:Class="XamlSamples.StaticConstantsPage"
             Title="Static Constants Page"
             Padding="{x:Static local:AppConstants.PagePadding}">

    <StackLayout>
       <Label Text="Hello, XAML!"
              TextColor="{x:Static local:AppConstants.BackgroundColor}"
              BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
              Font="{x:Static local:AppConstants.TitleFont}"
              HorizontalOptions="Center" />

      <BoxView WidthRequest="{x:Static sys:Math.PI}"
               HeightRequest="{x:Static sys:Math.E}"
               Color="{x:Static local:AppConstants.ForegroundColor}"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand"
               Scale="100" />
    </StackLayout>
</ContentPage>

Rozmiar wynikowego BoxView względem ekranu jest zależny od platformy:

Kontrolki używające rozszerzenia x:Static Markup

Inne standardowe rozszerzenia znaczników

Kilka rozszerzeń znaczników jest wewnętrznych dla języka XAML i obsługiwanych w Xamarin.Forms plikach XAML. Niektóre z nich nie są używane bardzo często, ale są niezbędne, gdy ich potrzebujesz:

  • Jeśli właściwość ma wartość inną niż null domyślna, ale chcesz ją ustawić na null, ustaw ją na {x:Null} rozszerzenie znaczników.
  • Jeśli właściwość jest typu Type, można przypisać ją do Type obiektu przy użyciu rozszerzenia {x:Type someClass}znaczników .
  • Tablice w języku XAML można definiować przy użyciu x:Array rozszerzenia znaczników. To rozszerzenie znaczników ma wymagany atrybut o nazwie Type , który wskazuje typ elementów w tablicy.
  • Rozszerzenie Binding znaczników zostało omówione w części 4. Podstawy powiązań danych.
  • Rozszerzenie RelativeSource znaczników jest omawiane w powiązaniach względnych.

Rozszerzenie znaczników ConstraintExpression

Rozszerzenia znaczników mogą mieć właściwości, ale nie są ustawione tak jak atrybuty XML. W rozszerzeniu znaczników ustawienia właściwości są oddzielone przecinkami, a żadne znaki cudzysłowu nie są wyświetlane w nawiasach klamrowych.

Można to zilustrować Xamarin.Forms za pomocą rozszerzenia znaczników o nazwie ConstraintExpression, który jest używany z klasą RelativeLayout . Możesz określić lokalizację lub rozmiar widoku podrzędnego jako stałą lub względem nadrzędnego lub innego nazwanego widoku. Składnia obiektu ConstraintExpression umożliwia ustawienie położenia lub rozmiaru widoku przy użyciu właściwości times innego Factor widoku oraz Constant. Cokolwiek bardziej złożonego niż wymaga to kodu.

Oto przykład:

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

    <RelativeLayout>

        <!-- Upper left -->
        <BoxView Color="Red"
                 RelativeLayout.XConstraint=
                     "{ConstraintExpression Type=Constant,
                                            Constant=0}"
                 RelativeLayout.YConstraint=
                     "{ConstraintExpression Type=Constant,
                                            Constant=0}" />
        <!-- Upper right -->
        <BoxView Color="Green"
                 RelativeLayout.XConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Width,
                                            Factor=1,
                                            Constant=-40}"
                 RelativeLayout.YConstraint=
                     "{ConstraintExpression Type=Constant,
                                            Constant=0}" />
        <!-- Lower left -->
        <BoxView Color="Blue"
                 RelativeLayout.XConstraint=
                     "{ConstraintExpression Type=Constant,
                                            Constant=0}"
                 RelativeLayout.YConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Height,
                                            Factor=1,
                                            Constant=-40}" />
        <!-- Lower right -->
        <BoxView Color="Yellow"
                 RelativeLayout.XConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Width,
                                            Factor=1,
                                            Constant=-40}"
                 RelativeLayout.YConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Height,
                                            Factor=1,
                                            Constant=-40}" />

        <!-- Centered and 1/3 width and height of parent -->
        <BoxView x:Name="oneThird"
                 Color="Red"
                 RelativeLayout.XConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Width,
                                            Factor=0.33}"
                 RelativeLayout.YConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Height,
                                            Factor=0.33}"
                 RelativeLayout.WidthConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Width,
                                            Factor=0.33}"
                 RelativeLayout.HeightConstraint=
                     "{ConstraintExpression Type=RelativeToParent,
                                            Property=Height,
                                            Factor=0.33}"  />

        <!-- 1/3 width and height of previous -->
        <BoxView Color="Blue"
                 RelativeLayout.XConstraint=
                     "{ConstraintExpression Type=RelativeToView,
                                            ElementName=oneThird,
                                            Property=X}"
                 RelativeLayout.YConstraint=
                     "{ConstraintExpression Type=RelativeToView,
                                            ElementName=oneThird,
                                            Property=Y}"
                 RelativeLayout.WidthConstraint=
                     "{ConstraintExpression Type=RelativeToView,
                                            ElementName=oneThird,
                                            Property=Width,
                                            Factor=0.33}"
                 RelativeLayout.HeightConstraint=
                     "{ConstraintExpression Type=RelativeToView,
                                            ElementName=oneThird,
                                            Property=Height,
                                            Factor=0.33}"  />
    </RelativeLayout>
</ContentPage>

Być może najważniejszą lekcją, którą należy wziąć z tego przykładu, jest składnia rozszerzenia znaczników znaczników: w nawiasach klamrowych rozszerzenia znaczników nie muszą być wyświetlane znaki cudzysłowu. Podczas wpisywania rozszerzenia znaczników w pliku XAML naturalne jest ujęcie wartości właściwości w cudzysłów. Oprzeć się pokusie!

Oto uruchomiony program:

Układ względny przy użyciu ograniczeń

Podsumowanie

Rozszerzenia znaczników XAML pokazane tutaj zapewniają ważną obsługę plików XAML. Ale być może najcenniejsze rozszerzenie znaczników XAML to Binding, które zostało omówione w następnej części tej serii, część 4. Podstawy powiązań danych.