使用 XAML 标记扩展
.NET 多平台应用 UI (.NET MAUI) XAML 标记扩展通过允许从各种源设置元素属性来帮助增强 XAML 的强大功能和灵活性。
例如,您通常如下设置 Color
的 BoxView 属性:
<BoxView Color="Blue" />
但是,您可能更愿意将 Color
属性设置为存储在资源字典中的值,或者将其设置为您已创建的类的静态属性的值,或者页面上其他元素类型为 Color 的属性,或者通过单独的色调、饱和度和亮度值构造而成。 所有这些选项都可以使用 XAML 标记扩展。
标记扩展是表达元素属性的不同方法。 .NET MAUI XAML 标记扩展通常由属性值标识,该属性值使用大括号括起。
<BoxView Color="{StaticResource themeColor}" />
大括号中的任何属性值 始终 XAML 标记扩展。 但是,也可以在不使用大括号的情况下引用 XAML 标记扩展。
注意
多个 XAML 标记扩展是 XAML 2009 规范的一部分。 它们出现在具有自定义 x
命名空间前缀的 XAML 文件中,通常使用此前缀引用。
除了本文中讨论的标记扩展之外,.NET MAUI 还包含以下标记扩展,并在其他文章中进行了讨论:
-
AppThemeBinding
- 根据当前系统主题指定要使用的资源。 有关详细信息,请参阅 AppThemeBinding 标记扩展。 -
Binding
- 在两个对象的属性之间建立链接。 有关详细信息,请参阅 数据绑定。 -
DynamicResource
- 响应资源字典中对象的变化。 有关详细信息,请参阅 动态样式。 -
FontImage
- 在可显示 ImageSource的任何视图中显示字体图标。 有关详细信息,请参阅 加载字体图标。 -
OnIdiom
- 根据运行应用程序的设备的成语自定义 UI 外观。 有关详细信息,请参阅 基于设备成语自定义 UI 外观。 -
OnPlatform
- 基于每个平台自定义 UI 外观。 有关详细信息,请参阅 基于平台自定义 UI 外观。 -
RelativeSource
- 设置绑定源相对于绑定目标的位置。 有关详细信息,请参阅 相对绑定。 -
StaticResource
- 引用资源字典中的对象。 有关详细信息,请参阅 资源字典。 -
TemplateBinding
- 从控件模板执行数据绑定。 有关详细信息,请参阅 控件模板。
x:Static 标记扩展
StaticExtension 类支持 x:Static
标记扩展。 该类有一个名为 Member
的属性,其类型为 string
,并且该属性可以设置为公共常量、静态属性、静态字段或枚举成员的名称。
使用 x:Static
的一种方法是首先定义具有某些常量或静态变量的类,例如此 AppConstants
类:
static class AppConstants
{
public static double NormalFontSize = 18;
}
以下 XAML 演示了在 Label.FontSize
属性元素标记之间实例化 StaticExtension 类的最详细方法:
<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
:
<Label Text="Label No. 2">
<Label.FontSize>
<x:Static Member="local:AppConstants.NormalFontSize" />
</Label.FontSize>
</Label>
通过将 StaticExtension 类和成员设置置于大括号中,可以进一步简化此语法。 生成的表达式直接设置为 FontSize
属性:
<Label Text="Label No. 3"
FontSize="{x:StaticExtension Member=local:AppConstants.NormalFontSize}" />
在此示例中,大括号内没有 引号。
StaticExtension 的 Member
属性不再是 XML 属性。 它而是标记扩展表达式的一部分。
正如在将其用作对象元素时可以缩写 x:StaticExtension
x:Static
一样,还可以在大括号内的表达式中缩写它:
<Label Text="Label No. 4"
FontSize="{x:Static Member=local:AppConstants.NormalFontSize}" />
StaticExtension 类具有引用属性 Member
的 ContentProperty
属性,该属性将此属性标记为类的默认内容属性。 对于用大括号表示的 XAML 标记扩展,可以消除表达式 Member=
部分:
<Label Text="Label No. 5"
FontSize="{x:Static local:AppConstants.NormalFontSize}" />
这是 x:Static
标记扩展的最常见形式。
XAML 示例的根标记还包含 .NET System
命名空间的 XML 命名空间声明。 这允许将 Label 字号设置为静态字段 Math.PI
。 这会产生相当小的文本,因此 Scale
属性设置为 Math.E
:
<Label Text="π × E sized text"
FontSize="{x:Static sys:Math.PI}"
Scale="{x:Static sys:Math.E}"
HorizontalOptions="Center" />
以下屏幕截图显示了 XAML 输出:
x:引用标记扩展
ReferenceExtension 类支持 x:Reference
标记扩展。 该类有一个名为 Name
的属性,类型为 string
。该属性被设置为页面上已通过 x:Name
命名的元素的名称。 此 Name
属性是 ReferenceExtension的内容属性,因此当 x:Reference
出现在大括号中时,不需要 Name=
。
x:Reference
标记扩展专用于数据绑定。 有关数据绑定的详细信息,请参阅 数据绑定。
下面的 XAML 示例演示了两种 x:Reference
与数据绑定的用法,第一个用于设置 Binding
对象的 Source
属性,第二个用于设置两个数据绑定的 BindingContext
属性:
<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}° rotation'}"
Rotation="{Binding Value}"
FontSize="24"
HorizontalOptions="Center"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
在此示例中,两个 x:Reference
表达式都使用 ReferenceExtension 类名的缩写版本,并消除表达式的 Name=
部分。 在第一个示例中,x:Reference
标记扩展嵌入 Binding
标记扩展中,Source
和 StringFormat
属性用逗号分隔。
以下屏幕截图显示了 XAML 输出:
x:Type 标记扩展
x:Type
标记扩展是 C# typeof
关键字的 XAML 等效项。 由 TypeExtension 类支持,该类定义了一个名为 TypeName
且类型为 string
的属性,该属性应设置为类或结构名称。
x:Type
标记扩展返回该类或结构的 Type
对象。
TypeName
是 TypeExtension的内容属性,因此当 x:Type
带有大括号出现时,无需使用 TypeName=
。
x:Type
标记扩展通常用于 x:Array
标记扩展。 有关详细信息,请参阅 x:Array 标记扩展。
以下 XAML 示例演示如何使用 x:Type
标记扩展实例化 .NET MAUI 对象并将其添加到 StackLayout。 XAML 包含三个 Button 元素,其 Command
属性设置为 Binding
,CommandParameter
属性设置为三种 .NET MAUI 视图的类型:
<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>
后台代码文件定义并初始化 CreateCommand
属性:
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:Array Type="{x:Type local:MyType(local:MyObject)}">
...
</x:Array>
可以将多个类型参数指定为带前缀的字符串参数,用逗号分隔:
<x:Array Type="{x:Type local:MyType(local:MyObject,x:Boolean)}">
...
</x:Array>
有关 XAML 中的泛型的详细信息,请参阅 泛型。
x:Array 标记扩展
使用 x:Array
标记扩展可以在标记中定义数组。
ArrayExtension 类支持它,该类定义两个属性:
-
Type
类型的Type
,指示数组中元素的类型。 此属性应设置为x:Type
标记扩展。 -
Items
属于IList
类型,该类型是项目本身的集合。 这是 ArrayExtension的内容属性。
x:Array
标记扩展本身永远不会出现在大括号中。 相反,x:Array
开始和结束标记分隔项列表。
以下 XAML 示例演示如何使用 x:Array
通过将 ItemsSource
属性设置为数组将项添加到 ListView:
<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:
注意
定义常见类型的数组(如字符串或数字)时,请使用 传递参数中列出的 XAML 语言基元标记。
x:Null 标记扩展
NullExtension 类支持 x:Null
标记扩展。 它没有属性,只是 C# null
关键字的 XAML 等效项。
以下 XAML 示例演示如何使用 x:Null
标记扩展:
<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>
在此示例中,定义了一个隐式 Style,它适用于 Label 并包含一个设置 FontFamily
属性为特定字体的 Setter。 然而,第三个 Label 将其 FontFamily
设置为 x:Null
,从而避免了使用隐式样式中定义的字体。
DataTemplate 标记扩展
DataTemplate 标记扩展使你可以将类型转换为 DataTemplate。
DataTemplateExtension 类支持,该类定义 string
类型的 TypeName
属性,该属性设置为要转换为 DataTemplate的类型的名称。
TypeName
属性是 DataTemplateExtension的内容属性。 因此,对于用大括号表示的 XAML 标记表达式,可以消除表达式的 TypeName=
部分。
注意
XAML 分析器允许将 DataTemplateExtension 类缩写为 DataTemplate。
此标记扩展的典型用法在 Shell 应用程序中,如以下示例所示:
<ShellContent Title="Monkeys"
Icon="monkey.png"
ContentTemplate="{DataTemplate views:MonkeysPage}" />
在此示例中,MonkeysPage
从 ContentPage 转换为 DataTemplate,并设置为 ShellContent.ContentTemplate
属性的值。 这确保 MonkeysPage
只在导航到页面时创建,而不是在应用程序启动时。
有关 Shell 应用的详细信息,请参阅 Shell。