Расширения разметки 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:
Другие расширения разметки
Несколько расширений разметки являются встроенными в XAML и поддерживаются в XAML .NET MAUI. Некоторые из них не используются очень часто, но являются важными, если они нужны:
- Если свойство имеет значение, отличное
null
от значения по умолчанию, но вы хотите задать егоnull
в качестве значения, задайте его расширение разметки{x:Null}
. - Если свойство имеет тип
Type
, его можно назначитьType
объекту с помощью расширения{x:Type someClass}
разметки. - Массивы в XAML можно определить с помощью
x:Array
расширения разметки. Это расширение разметки имеет обязательный атрибут,Type
указывающий тип элементов в массиве.
Дополнительные сведения о расширениях разметки XAML см. в разделе "Использование расширений разметки XAML".
Следующие шаги
Привязки данных .NET MAUI позволяют связать свойства двух объектов таким образом, чтобы изменение в одном из них приводило к изменению в другой.