Поделиться через


Расширения разметки XAML

Просмотрите пример. Обзор примера

Расширения разметки XAML для многоплатформенных приложений .NET (.NET MAUI) позволяют задавать свойства объектам или значениям, на которые ссылаются косвенно из других источников. Расширения разметки XAML особенно важны для совместного использования объектов и ссылки на константы, используемые во всем приложении, но они находят их большую служебную программу в привязках данных.

Как правило, с помощью XAML можно задать свойства объекта явным значениям, таким как строка, число, член перечисления или строка, преобразованная в значение за кулисами. Однако иногда свойства должны вместо этого ссылаться на значения, определенные в другом месте или которые могут потребовать немного обработки по коду во время выполнения. В этих целях доступны расширения разметки XAML.

Расширения разметки XAML так называются, так как они поддерживаются кодом в классах, реализующих IMarkupExtension. Кроме того, можно написать собственные расширения разметки.

Во многих случаях расширения разметки XAML мгновенно распознаются в XAML-файлах, так как они отображаются как значения атрибутов, разделенные фигурными скобками, { и }, но иногда расширения разметки также отображаются в разметке как обычные элементы.

Внимание

Расширения разметки могут иметь свойства, но они не задаются как атрибуты XML. В расширении разметки параметры свойств разделены запятыми, а кавычки не отображаются в фигурных скобках.

Общие ресурсы

Некоторые страницы XAML содержат несколько представлений со свойствами, заданными для одинаковых значений. Например, многие параметры свойств для этих Button объектов одинаковы:

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

Если одно из этих свойств необходимо изменить, вы можете сделать это изменение только один раз, а не три раза. Если бы это был код, скорее всего, вы будете использовать константы и статические объекты только для чтения, чтобы обеспечить согласованность таких значений и легко изменять.

В XAML одним из популярных решений является хранение таких значений или объектов в словаре ресурсов. Класс VisualElement определяет свойство с именем Resources типа ResourceDictionary, которое является словарем с ключами типа string и значений типа object. Объекты можно поместить в этот словарь, а затем ссылаться на них из разметки, все в XAML.

Чтобы использовать словарь ресурсов на странице, включите пару Resources тегов элементов свойств в верхней части страницы и добавьте ресурсы в эти теги. Объекты и значения различных типов можно добавить в словарь ресурсов. Эти типы должны быть экземплярами. Например, они не могут быть абстрактными классами. Эти типы также должны иметь открытый конструктор без параметров. Для каждого элемента требуется ключ словаря, указанный атрибутом 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>

В этом примере два ресурса являются значениями типа LayoutOptionsструктуры, и каждый из них имеет уникальный ключ и один или два набора свойств. В коде и разметке гораздо чаще используются статические поля LayoutOptions, но здесь удобнее задать свойства.

Примечание.

Необязательные ResourceDictionary теги можно включить в качестве дочернего Resources элемента тегов.

Затем ресурсы можно использовать Button объектами с помощью StaticResource расширения разметки XAML для задания их HorizontalOptions и VerticalOptions свойств:

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

StaticResource Расширение разметки всегда разделено фигурными скобками и включает ключ словаря. Имя StaticResource отличает его от DynamicResourceтого, что также поддерживает .NET MAUI. DynamicResource предназначен для ключей словаря, связанных со значениями, которые могут изменяться во время выполнения, а StaticResource доступ к элементам из словаря осуществляется только один раз при создании элементов на странице. Всякий раз, когда средство синтаксического анализа XAML обнаруживает StaticResource расширение разметки, выполняет поиск по визуальному дереву и использует первое ResourceDictionary , что оно встречается с этим ключом.

Необходимо хранить двойные значения в словаре для BorderWidthсвойств Rotationи FontSize свойств. XAML удобно определяет теги для распространенных типов данных, таких как x:Double и 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>

На эти дополнительные три ресурса можно ссылаться так же, как LayoutOptions и на значения:

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

Для ресурсов типа Colorможно использовать те же строковые представления, которые используются при непосредственном назначении атрибутов этих типов. Преобразователи типов, включенные в .NET MAUI, вызываются при создании ресурса. Кроме того, можно использовать OnPlatform класс в словаре ресурсов для определения различных значений платформ. В следующем примере этот класс используется для задания различных цветов текста:

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

Ресурс OnPlatform получает x:Key атрибут, так как это объект в словаре и x:TypeArguments атрибут, так как это универсальный класс. Атрибуты iOSпреобразуются Android в Color значения при инициализации объекта.

В следующем примере показаны три кнопки, обращающиеся к шести общим значениям:

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

На следующем снимне экрана проверяется согласованное стилизация:

Снимок экрана: элементы управления стилем.

Хотя в верхней части страницы обычно определяется Resources коллекция, вы можете иметь Resources коллекции на других элементах на странице. Например, в следующем примере показаны ресурсы, добавленные в StackLayout:

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

Одним из наиболее распространенных типов объектов, хранящихся в словарях ресурсов, является .NET MAUI Style, который определяет коллекцию параметров свойств. Дополнительные сведения о стилях см. в статье "Стили приложений с помощью XAML".

Примечание.

Назначение словаря ресурсов — совместное использование объектов. Поэтому не имеет смысла помещать такие элементы управления, как Label словарь ресурсов или Button в него. Визуальные элементы нельзя совместно использовать, так как один и тот же экземпляр не может отображаться дважды на странице.

Расширение разметки x:Static

StaticResource Помимо расширения разметки, также существует x:Static расширение разметки. Однако при StaticResource возврате объекта из словаряx:Static ресурсов обращается к общедоступному статическому полю, общедоступному статическому свойству, общедоступному полю константы или члену перечисления.

Примечание.

StaticResource Расширение разметки поддерживается реализациями XAML, определяющими словарь ресурсов, в то время как x:Static является встроенной частью XAML, как x показывает префикс.

В следующем примере показано, как x:Static явно ссылаться на статические поля и элементы перечисления:

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

Основное использование расширения разметки x:Static заключается в ссылке на статические поля или свойства из собственного кода. Например, вот AppConstants класс, содержащий некоторые статические поля, которые могут потребоваться использовать на нескольких страницах в приложении:

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

Чтобы ссылаться на статические поля этого класса в XAML-файле, необходимо использовать объявление пространства имен XML, чтобы указать расположение этого файла. Каждое дополнительное объявление пространства имен XML определяет новый префикс. Для доступа к классам, локальным к пространству имен корневого приложения, например AppConstants, можно использовать префикс local. Объявление пространства имен должно указывать имя пространства имен СРЕДЫ CLR (clR), также известное как имя пространства имен .NET, которое отображается в определении C# namespace или в директиве using :

xmlns:local="clr-namespace:XamlSamples"

Можно также определить объявления пространства имен XML для пространств имен .NET. Например, вот sys префикс стандартного пространства имен .NET System , которое находится в сборке netstandard . Так как это другая сборка, необходимо также указать имя сборки, в данном случае netstandard:

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

Примечание.

За ключевым словом clr-namespace следует двоеточие, а затем имя пространства имен .NET, за которым следует точка с запятой, ключевое слово assembly, знак равенства и имя сборки.

Затем статические поля можно использовать после объявления пространства имен 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>

В этом примере BoxView измерения задаются Math.PI и Math.Eмасштабируются по коэффициенту 100:

Снимок экрана: элементы управления с расширением разметки x:Static.

Другие расширения разметки

Несколько расширений разметки являются встроенными в XAML и поддерживаются в XAML .NET MAUI. Некоторые из них не используются очень часто, но являются важными, если они нужны:

  • Если свойство имеет значение, отличное null от значения по умолчанию, но вы хотите задать его nullв качестве значения, задайте его расширение разметки {x:Null} .
  • Если свойство имеет тип Type, его можно назначить Type объекту с помощью расширения {x:Type someClass}разметки.
  • Массивы в XAML можно определить с помощью x:Array расширения разметки. Это расширение разметки имеет обязательный атрибут, Type указывающий тип элементов в массиве.

Дополнительные сведения о расширениях разметки XAML см. в разделе "Использование расширений разметки XAML".

Следующие шаги

Привязки данных .NET MAUI позволяют связать свойства двух объектов таким образом, чтобы изменение в одном из них приводило к изменению в другой.