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

Завершено

Большая часть вашего определения XAML будет создаваться во время компиляции. Часто вы заранее знаете, где должны находиться элементы, какие цвета и шрифты вам нужны и какие литеральные значения следует назначить свойствам.

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

В этом уроке вы узнаете, как создавать и использовать расширения разметки.

Что такое расширение разметки?

Расширение разметки — это класс, используемый в XAML для доступа к значениям среды выполнения. Предположим, у вас есть много меток, определенных в пользовательском интерфейсе XAML, и вы хотите задать FontSize для свойства одинаковое значение во всем приложении, чтобы убедиться, что все стили меток согласованы. Свойство можно задать FontSize с помощью XAML, как показано в следующем примере:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="28"
            HorizontalOptions="CenterAndExpand"/>

Вы можете повторить этот же параметр для каждой метки, но что, если вы хотите изменить это значение позже? Вам нужно найти каждый экземпляр этого свойства и внести изменения. Кроме того, предположим, что вы не знаете, какое значение следует использовать; его можно вычислить во время выполнения на основе таких факторов, как ориентация устройства, разрешение экрана или другие рекомендации. Для таких случаев нужно что-то более сложное, чем жестко заданный литерал. Здесь полезно расширение разметки. Расширения разметки обеспечивают гибкость при получении значения, которое используется в XAML.

Создание расширения разметки

Расширение разметки — это класс, реализующий интерфейс Microsoft.Maui.Controls.Xaml.IMarkupExtension . Этот интерфейс определяет один метод с именем ProvideValueсо следующей сигнатурой:

public object ProvideValue(IServiceProvider serviceProvider)
{
    ...
}

Цель этого метода — указать значение разметки XAML. Обратите внимание, что возвращается значение с типом object, то есть это может быть значение любого типа, пригодного для того места, где оно используется. Например, в расширении разметки, которое вычисляет и возвращает размер шрифта, возвращаемый тип должен быть.double

Параметр serviceProvider содержит контекстные сведения о том, где расширение разметки используется в коде XAML. Помимо других элементов информации, он определяет элемент управления, к которому применяется расширение.

Расширение разметки можно сохранить простым FontSize для свойства. В следующем примере MainPage класс предоставляет double поле с именем MyFontSize. Класс GlobalFontSizeExtension реализует IMarkupExtension интерфейс, а ProvideValue метод возвращает значение переменной MyFontSize :

namespace MyMauiApp;

public partial class MainPage : ContentPage
{
    public const double MyFontSize = 28;

    public MainPage()
    {
        InitializeComponent();
        ...
    }
    ...
}

public class GlobalFontSizeExtension : IMarkupExtension
{
    public object ProvideValue(IServiceProvider serviceProvider)
    {
        return MainPage.MyFontSize;
    }
}

Примечание.

Поле MyFontSize должно быть static членом MainPage класса, чтобы его можно было ссылаться в ProvideValue методе таким образом. Рекомендуется, чтобы в этом случае переменная также была константой. const имеет значение static.

Метод ProvideValue также может внести изменения в возвращаемое значение в зависимости от ориентации и форм-фактора устройства.

Применение расширения разметки к элементу управления в XAML

Чтобы использовать расширение разметки в коде XAML, добавьте пространство имен, содержащее GlobalFontSizeExtension класс, в список пространств имен в теге ContentPage . В следующем примере это пространство имен присваивается псевдониму mycode:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:mycode="clr-namespace:MyMauiApp"
             x:Class="MyMauiApp.MainPage">

Расширение разметки можно использовать для задания FontSize свойства следующим образом. Обратите внимание, что расширение разметки имеет расширение суффикса в его имени. XAML распознает этот суффикс, то есть его не обязательно указывать при вызове расширения из кода XAML. В следующем примере класс ссылается просто такGlobalFontSize:GlobalFontSizeExtension

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="{mycode:GlobalFontSize}"
            HorizontalOptions="CenterAndExpand"/>

Вы можете применить одно и то же расширение разметки в коде XAML для любого элемента управления, который должен указывать размер шрифта. Позже, если вы решите изменить размер шрифта, необходимо изменить определение переменной MyFontSize в MainPage классе.

Класс StaticExtension

Так же полезно, как GlobalFontSize расширение разметки, вряд ли вы создадите такое расширение. Причина этого проста. .NET MAUI уже предоставляет более обобщенное расширение, которое позволяет ссылаться на любое статическое значение в коде. Это расширение называется StaticExtensionили Static коротко. В следующем коде показан базовый контур этого класса расширения:

[ContentProperty ("Member")]
public class StaticExtension : IMarkupExtension
{
    public string Member {get; set;}
    public object ProvideValue (IServiceProvider serviceProvider)
    {
        ...
    }
}

Примечание.

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

Чтобы использовать этот класс в коде XAML, укажите имя статической переменной, которую нужно ссылаться в свойстве Member , и ProvideValue метод возвращает значение в этой переменной. Следующий пример демонстрирует такое использование:

<Label Text="Hello, World!"
            Grid.Row="0"
            SemanticProperties.HeadingLevel="Level1"
            FontSize="{x:Static Member=mycode:MainPage.MyFontSize}"
            HorizontalOptions="CenterAndExpand"/>

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

Проверка знаний

1.

Какое расширение разметки позволяет задать свойство XAML статическим значением, определенным в классе code-behind?

2.

Какой интерфейс используется для создания пользовательского расширения разметки?