Расширения разметки 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 предоставляет набор других классов расширений разметки, которые можно использовать для таких сценариев, как привязка данных, ссылка на динамические ресурсы и стили, а также обработка массивов данных.