Прочитать на английском

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


Использование расширений разметки XAML

Просмотр образца. Просмотреть образец

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

Например, вы обычно задаете свойство Color для BoxView следующим образом:

XAML
<BoxView Color="Blue" />

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

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

XAML
<BoxView Color="{StaticResource themeColor}" />

Любое значение атрибута в фигурных скобках всегда является расширением разметки в XAML. Однако расширения разметки XAML также можно использовать без использования фигурных скобок.

Примечание

Несколько расширений разметки XAML являются частью спецификации XAML 2009. Они отображаются в XAML-файлах с обычным префиксом пространства имен x, и обычно ссылаются на них с этим префиксом.

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

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

Расширение разметки x:Static поддерживается классом StaticExtension. Класс имеет одно свойство с именем Member типа string, которое вы задаете для имени общедоступной константы, статического свойства, статического поля или элемента перечисления.

Один из способов использования x:Static — сначала определить класс с некоторыми константами или статическими переменными, такими как этот класс AppConstants:

C#
static class AppConstants
{
    public static double NormalFontSize = 18;
}

Следующий код XAML демонстрирует наиболее подробный подход к созданию экземпляра класса StaticExtension между тегами элементов свойств Label.FontSize:

XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:sys="clr-namespace:System;assembly=netstandard"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.StaticDemoPage"
             Title="x:Static Demo">
    <StackLayout Margin="10, 0">
        <Label Text="Label No. 1">
            <Label.FontSize>
                <x:StaticExtension Member="local:AppConstants.NormalFontSize" />
            </Label.FontSize>
        </Label>
        ···
    </StackLayout>
</ContentPage>

Средство синтаксического анализа XAML также позволяет сократить класс StaticExtension как x:Static:

XAML
<Label Text="Label No. 2">
    <Label.FontSize>
        <x:Static Member="local:AppConstants.NormalFontSize" />
    </Label.FontSize>
</Label>

Этот синтаксис можно упростить, поместив класс StaticExtension и параметр члена в фигурные скобки. Результирующее выражение задается непосредственно атрибуту FontSize:

XAML
<Label Text="Label No. 3"
       FontSize="{x:StaticExtension Member=local:AppConstants.NormalFontSize}" />

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

Так же, как можно сократить x:StaticExtension до x:Static при использовании его в качестве элемента объекта, его можно сократить и в выражении в фигурных скобках:

XAML
<Label Text="Label No. 4"
       FontSize="{x:Static Member=local:AppConstants.NormalFontSize}" />

Класс StaticExtension имеет атрибут ContentProperty, ссылающийся на свойство Member, которое помечает это свойство как свойство содержимого по умолчанию класса. Для расширений разметки XAML, задаваемых при помощи фигурных скобок, можно исключить часть выражения Member=:

XAML
<Label Text="Label No. 5"
       FontSize="{x:Static local:AppConstants.NormalFontSize}" />

Это наиболее распространенная форма расширения разметки x:Static.

Корневой тег примера XAML также содержит объявление пространства имен XML для пространства имен .NET System. Это позволяет задать размер шрифта Label с помощью статического поля Math.PI. Это приводит к довольно маленькому тексту, поэтому для свойства Scale задано значение Math.E:

XAML
<Label Text="&#x03C0; &#x00D7; E sized text"
       FontSize="{x:Static sys:Math.PI}"
       Scale="{x:Static sys:Math.E}"
       HorizontalOptions="Center" />

На следующем снимку экрана показаны выходные данные XAML:

x:Static демонстрация.

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

Расширение разметки x:Reference поддерживается классом ReferenceExtension. Класс имеет одно свойство с именем Name типа string, которое устанавливается на имя элемента на странице, которому присвоено имя с помощью x:Name. Это свойство Name является свойством содержимого ReferenceExtension, поэтому Name= не требуется, если x:Reference отображается в фигурных скобках. Расширение разметки x:Reference используется исключительно с привязками данных. Дополнительные сведения о привязках данных см. в привязки данных.

В следующем примере XAML показано два использования x:Reference с привязками данных, первое, где оно используется для задания свойства Source объекта Binding, а второй — для задания свойства BindingContext для двух привязок данных:

XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.ReferenceDemoPage"
             x:Name="page"
             Title="x:Reference Demo">    
    <StackLayout Margin="10, 0">        
        <Label x:DataType="ContentPage"
               Text="{Binding Source={x:Reference page},
                              StringFormat='The type of this page is {0}'}"
               FontSize="18"
               VerticalOptions="Center"
               HorizontalTextAlignment="Center" />
        <Slider x:Name="slider"
                Maximum="360"
                VerticalOptions="Center" />
        <Label x:DataType="Slider"
               BindingContext="{x:Reference slider}"
               Text="{Binding Value, StringFormat='{0:F0}&#x00B0; rotation'}"
               Rotation="{Binding Value}"
               FontSize="24"
               HorizontalOptions="Center"
               VerticalOptions="Center" />        
    </StackLayout>
</ContentPage>

В этом примере оба выражения x:Reference используют сокращённое имя класса ReferenceExtension и исключают часть выражения Name=. В первом примере расширение разметки x:Reference внедрено в расширение разметки Binding, а свойства Source и StringFormat разделены запятыми.

На следующем снимку экрана показаны выходные данные XAML:

демонстрации x:Reference.

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

Расширение разметки x:Type является эквивалентом XAML ключевого слова typeof C#. Он поддерживается классом TypeExtension, который определяет свойство с именем TypeName типа string, которое должно быть присвоено имени класса или структуры. Расширение разметки x:Type возвращает объект Type этого класса или структуры. TypeName является свойством содержимого TypeExtension, поэтому TypeName= не требуется, если x:Type отображается с фигурными скобками.

Расширение разметки x:Type обычно используется с расширением разметки x:Array. Дополнительные сведения см. в расширении разметки x:Array .

В следующем примере XAML демонстрируется, как использовать расширение разметки x:Type для создания объектов .NET MAUI и добавления их в StackLayout. XAML состоит из трех элементов Button с установленными свойствами Command равными Binding и свойствами CommandParameter, установленными для типов трех представлений .NET MAUI.

XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MarkupExtensions"
             x:Class="MarkupExtensions.TypeDemoPage"
             Title="x:Type Demo"
             x:DataType="local:TypeDemoPage">
    <StackLayout x:Name="stackLayout"
                 Padding="10, 0">
        <Button Text="Create a Slider"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Command="{Binding CreateCommand}"
                CommandParameter="{x:Type Slider}" />
        <Button Text="Create a Stepper"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Command="{Binding CreateCommand}"
                CommandParameter="{x:Type Stepper}" />
        <Button Text="Create a Switch"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Command="{Binding CreateCommand}"
                CommandParameter="{x:Type Switch}" />
    </StackLayout>
</ContentPage>

Файл code-behind определяет и инициализирует свойство CreateCommand:

C#
public partial class TypeDemoPage : ContentPage
{
    public ICommand CreateCommand { get; private set; }

    public TypeDemoPage()
    {
        InitializeComponent();

        CreateCommand = new Command<Type>((Type viewType) =>
        {
            View view = (View)Activator.CreateInstance(viewType);
            view.VerticalOptions = LayoutOptions.Center;
            stackLayout.Add(view);
        });

        BindingContext = this;
    }
}

При нажатии Button создается новый экземпляр аргумента CommandParameter и добавляется в StackLayout. Три объекта Button затем совместно используют страницу с динамически созданными представлениями:

демонстрация x:Type.

Универсальные типы можно указать с расширением разметки x:Type, указав универсальное ограничение в качестве префикса строкового аргумента в скобках:

XAML
<x:Array Type="{x:Type local:MyType(local:MyObject)}">
    ...
</x:Array>

Несколько аргументов типа можно указать как префиксированные строковые аргументы, разделенные запятыми:

XAML
<x:Array Type="{x:Type local:MyType(local:MyObject,x:Boolean)}">
    ...
</x:Array>

Дополнительные сведения об обобщениях в XAML см. в Generics.

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

Расширение разметки x:Array позволяет определить массив в разметке. Он поддерживается классом ArrayExtension, который определяет два свойства:

  • Type типа Type, который указывает на тип элементов в массиве. Это свойство должно быть установлено в расширение разметки типа x:Type.
  • Items типа IList, который представляет собой коллекцию самих элементов. Это свойство содержимого ArrayExtension.

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

В следующем примере XAML показано, как использовать x:Array для добавления элементов в ListView путем задания свойства ItemsSource массиву:

XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.ArrayDemoPage"
             Title="x:Array Demo Page">
    <ListView Margin="10">
        <ListView.ItemsSource>
            <x:Array Type="{x:Type Color}">
                <Color>Aqua</Color>
                <Color>Black</Color>
                <Color>Blue</Color>
                <Color>Fuchsia</Color>
                <Color>Gray</Color>
                <Color>Green</Color>
                <Color>Lime</Color>
                <Color>Maroon</Color>
                <Color>Navy</Color>
                <Color>Olive</Color>
                <Color>Pink</Color>
                <Color>Purple</Color>
                <Color>Red</Color>
                <Color>Silver</Color>
                <Color>Teal</Color>
                <Color>White</Color>
                <Color>Yellow</Color>
            </x:Array>
        </ListView.ItemsSource>
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="Color">
                <ViewCell>
                    <BoxView Color="{Binding}"
                             Margin="3" />
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</ContentPage>  

В этом примере ViewCell создает простую BoxView для каждой записи цвета:

x:Array демонстрация.

Примечание

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

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

Расширение разметки x:Null поддерживается классом NullExtension. Он не имеет свойств и является просто эквивалентом XAML ключевого слова null C#.

В следующем примере XAML показано, как использовать расширение разметки x:Null:

XAML
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MarkupExtensions.NullDemoPage"
             Title="x:Null Demo">
    <ContentPage.Resources>
        <Style TargetType="Label">
            <Setter Property="FontSize" Value="48" />
            <Setter Property="FontFamily" Value="OpenSansRegular" />
        </Style>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <Label Text="Text 1" />
        <Label Text="Text 2" />
        <Label Text="Text 3"
               FontFamily="{x:Null}" />
        <Label Text="Text 4" />
        <Label Text="Text 5" />
    </StackLayout>
</ContentPage>      

В этом примере для Label определяется неявная Style, которая включает Setter, где свойство FontFamily устанавливается на определенный шрифт. Однако третий Label избегает использования шрифта, определенного в неявном стиле, задав FontFamily значение x:Null:

демонстрация x:Null.

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

Расширение разметки DataTemplate позволяет преобразовать тип в DataTemplate. Он поддерживается классом DataTemplateExtension, который определяет свойство TypeName типа string, которое присваивается имени типа, который необходимо преобразовать в DataTemplate. Свойство TypeName является свойством содержимого DataTemplateExtension. Поэтому для выражений разметки XAML, выраженных с фигурными скобками, можно исключить TypeName= часть выражения.

Примечание

Средство синтаксического анализа XAML позволяет сократить класс DataTemplateExtension как DataTemplate.

Обычное использование этого расширения разметки в приложении Shell, как показано в следующем примере:

XAML
<ShellContent Title="Monkeys"
              Icon="monkey.png"
              ContentTemplate="{DataTemplate views:MonkeysPage}" />

В этом примере MonkeysPage преобразуется из ContentPage в DataTemplate, который задается в качестве значения свойства ShellContent.ContentTemplate. Это гарантирует, что MonkeysPage создается только при переходе на страницу, а не при запуске приложения.

Дополнительную информацию о приложениях Shell см. в разделе .