Udostępnij za pośrednictwem


Rozszerzenia struktury znaczników XAML

Przeglądaj przykład. Przeglądanie przykładu

Rozszerzenia znaczników XAML interfejsu użytkownika aplikacji wieloplatformowej platformy .NET (.NET MAUI) umożliwiają 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.

Zazwyczaj używasz języka XAML 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.

Rozszerzenia znaczników XAML są tak nazwane, ponieważ są one wspierane przez kod w klasach implementujących IMarkupExtension. Istnieje również możliwość zapisania własnych niestandardowych rozszerzeń znaczników.

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

Ważne

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.

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://schemas.microsoft.com/dotnet/2021/maui"
             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="Center"
                BorderWidth="3"
                Rotation="-15"
                TextColor="Red"
                FontSize="24" />
        <Button Text="Do that!"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                BorderWidth="3"
                Rotation="-15"
                TextColor="Red"
                FontSize="24" />
        <Button Text="Do the other thing!"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                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 właściwości-element w górnej części strony i dodaj zasoby w tych tagach. Obiekty i wartości różnych typów można dodać do słownika zasobó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 :

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SharedResourcesPage"
             Title="Shared Resources Page">
    <ContentPage.Resources>
        <LayoutOptions x:Key="horzOptions"
                       Alignment="Center" />
        <LayoutOptions x:Key="vertOptions"
                       Alignment="Center" />
    </ContentPage.Resources>
    ...
</ContentPage>

W tym przykładzie dwa zasoby są wartościami typu LayoutOptionsstruktury , a każdy z nich ma unikatowy klucz i jedną lub dwie właściwości ustawione. 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.

Uwaga

Opcjonalne ResourceDictionary tagi można dołączać jako element podrzędny Resources tagów.

Zasoby mogą być następnie używane przez Button obiekty przy użyciu StaticResource rozszerzenia znaczników XAML w celu ustawienia ich HorizontalOptions właściwości i VerticalOptions :

<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 obsługuje również program .NET MAUI. DynamicResource jest przeznaczony dla kluczy słownika skojarzonych z wartościami, które mogą ulec zmianie w czasie wykonywania, podczas gdy StaticResource są tworzone elementy ze słownika tylko raz. Za każdym razem, gdy analizator XAML napotka StaticResource rozszerzenie znaczników, wyszukuje drzewo wizualne i używa pierwszego ResourceDictionary napotkanego klucza zawierającego ten klucz.

Należy przechowywać dublety w słowniku BorderWidthdla właściwości , Rotationi FontSize . Język XAML wygodnie definiuje tagi dla typowych typów danych, takich jak x:Double i x:Int32:

<ContentPage.Resources>
        <LayoutOptions x:Key="horzOptions"
                       Alignment="Center" />
        <LayoutOptions x:Key="vertOptions"
                       Alignment="Center" />
        <x:Double x:Key="borderWidth">3</x:Double>
        <x:Double x:Key="rotationAngle">-15</x:Double>
        <x:Double x:Key="fontSize">24</x:Double>        
</ContentPage.Resources>

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

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

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 zawarte w interfejsie MAUI platformy .NET są wywoływane podczas tworzenia zasobu. Można również użyć OnPlatform klasy w słowniku zasobów, aby zdefiniować różne wartości dla platform. W poniższym przykładzie użyto tej klasy do ustawiania różnych kolorów tekstu:

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

Zasób OnPlatform pobiera x:Key atrybut, ponieważ jest to obiekt w słowniku i x:TypeArguments atrybut, ponieważ jest to klasa ogólna. Atrybuty iOSi są Android konwertowane na Color wartości podczas inicjowania obiektu.

W poniższym przykładzie przedstawiono trzy przyciski, które uzyskują dostęp do sześciu wartości udostępnionych:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.SharedResourcesPage"
             Title="Shared Resources Page">
    <ContentPage.Resources>
        <LayoutOptions x:Key="horzOptions"
                       Alignment="Center" />
        <LayoutOptions x:Key="vertOptions"
                       Alignment="Center" />
        <x:Double x:Key="borderWidth">3</x:Double>
        <x:Double x:Key="rotationAngle">-15</x:Double>
        <x:Double x:Key="fontSize">24</x:Double>    
        <OnPlatform x:Key="textColor"
                    x:TypeArguments="Color">
            <On Platform="iOS" Value="Red" />
            <On Platform="Android" Value="Aqua" />
            <On Platform="WinUI" Value="#80FF80" />
        </OnPlatform>
    </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>

Poniższy zrzut ekranu weryfikuje spójny styl:

Zrzut ekranu przedstawiający stylowane kontrolki.

Chociaż często definiuje Resources się kolekcję w górnej części strony, kolekcje mogą znajdować Resources się na innych elementach na stronie. Na przykład w poniższym przykładzie przedstawiono zasoby dodane do elementu StackLayout:

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

Jednym z najpopularniejszych typów obiektów przechowywanych w słownikach zasobów jest program .NET MAUI Style, który definiuje kolekcję ustawień właściwości. Aby uzyskać więcej informacji na temat stylów, zobacz Style apps using XAML (Aplikacje stylów przy użyciu języka XAML).

Uwaga

Celem słownika zasobów jest udostępnianie obiektów. W związku z tym nie ma sensu umieszczać kontrolek, takich jak Label lub Button w słowniku zasobów. Nie można udostępnić elementów wizualnych, ponieważ to samo wystąpienie nie może być wyświetlane dwa razy na stronie.

x:Static — Rozszerzenie znaczników

Oprócz StaticResource rozszerzenia znaczników istnieje również x:Static rozszerzenie znaczników. Jednak podczas zwracania StaticResource obiektu ze słownika zasobów uzyskujex:Static dostęp do publicznego pola statycznego, właściwości statycznej publicznej, pola stałej publicznej lub elementu członkowskiego wyliczenia.

Uwaga

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.

W poniższym przykładzie pokazano, 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 Colors.Aqua}" />

Głównym zastosowaniem x:Static rozszerzenia znaczników jest odwoływanie się do pól statycznych lub właściwości z własnego kodu. Oto na przykład AppConstants klasa zawierająca niektóre pola statyczne, których można użyć na wielu stronach w całej aplikacji:

namespace XamlSamples
{
    static class AppConstants
    {
        public static readonly Color BackgroundColor = Colors.Aqua;
        public static readonly Color ForegroundColor = Colors.Brown;
    }
}

Aby odwołać się do pól statycznych tej klasy w pliku XAML, należy użyć deklaracji przestrzeni nazw XML, aby wskazać, gdzie znajduje się ten plik. Każda dodatkowa deklaracja przestrzeni nazw XML definiuje nowy prefiks. Aby uzyskać dostęp do klas lokalnych w przestrzeni nazw aplikacji głównej, takiej jak AppConstants, można użyć 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. Oto na przykład sys prefiks dla standardowej przestrzeni nazw platformy .NET System , która znajduje się w netstandard zestawie. Ponieważ jest to inny zestaw, należy również określić nazwę zestawu, w tym przypadku netstandard:

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

Uwaga

Po słowie kluczowym clr-namespace następuje dwukropek, a następnie nazwa przestrzeni nazw platformy .NET, po której następuje średnik, słowo kluczowe assembly, znak równości i nazwa zestawu.

Pola statyczne można następnie używać po zadeklarowaniu przestrzeni nazw XML:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             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="5,25,5,0">
    <StackLayout>
       <Label Text="Hello, XAML!"
              TextColor="{x:Static local:AppConstants.BackgroundColor}"
              BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
              FontAttributes="Bold"
              FontSize="30"
              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>

W tym przykładzie BoxView wymiary są ustawione na Math.PI i Math.E, ale skalowane według współczynnika 100:

Zrzut ekranu przedstawiający kontrolki używające rozszerzenia znaczników x:Static.

Inne rozszerzenia znaczników

Kilka rozszerzeń znaczników jest wewnętrznych dla języka XAML i obsługiwanych w języku XAML .NET MAUI. 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.

Aby uzyskać więcej informacji na temat rozszerzeń znaczników XAML, zobacz Korzystanie z rozszerzeń znaczników XAML.

Następne kroki

Powiązania danych programu .NET MAUI umożliwiają połączenie właściwości dwóch obiektów, dzięki czemu zmiana w jednym powoduje zmianę w drugiej.