XAML 标记扩展支持从各种源设置元素属性,从而帮助增强 XAML 的功能和灵活性。 多个 XAML 标记扩展是 XAML 2009 规范的一部分。 它们出现在 XAML 文件中,带有惯用的 x 命名空间前缀,并且通常用此前缀来进行引用。 本文讨论以下标记扩展:
x:Static- 引用静态属性、字段或枚举成员。x:Reference- 引用页面上的命名元素。x:Type- 将属性设置为System.Type对象。x:Array- 构造特定类型的对象的数组。x:Null- 将属性设置为值null。OnPlatform- 基于每个平台自定义 UI 外观。OnIdiom- 根据运行应用程序的设备的惯用法自定义 UI 外观。DataTemplate- 将类型转换为DataTemplate。FontImage- 在任何可以显示ImageSource的视图中显示字体图标。AppThemeBinding- 根据当前系统主题使用资源。
其他 XAML 标记扩展历来受到其他 XAML 实现的支持,也受 Xamarin.Forms 的支持。 其他文章更全面地介绍了这些内容:
StaticResource- 引用资源字典中的对象,如资源字典一文中所述。DynamicResource- 响应资源字典中对象的更改,如动态样式一文中所述。Binding- 在两个对象的属性之间建立链接,如数据绑定一文中所述。TemplateBinding- 从控件模板执行数据绑定,如 Xamarin.Forms 控件模板一文中所述。RelativeSource- 设置相对于绑定目标位置的绑定源,如相对绑定一文中所述。
RelativeLayout 布局使用自定义标记扩展 ConstraintExpression。 此标记扩展在 RelativeLayout 一文中予以介绍。
x:Static 标记扩展
StaticExtension 类支持 x:Static 标记扩展。 该类具有类型为 string 的名为 Member 的单一属性,你可以将其设置为公共常量、静态属性、静态字段或枚举成员的名称。
使用 x:Static 的一种常见方法是首先定义具有某些常量或静态变量的类,例如这个微小的 AppConstants 类:
static class AppConstants
{
public static double NormalFontSize = 18;
}
“x:Static 演示”页面展示了多种使用 x:Static 标记扩展的方法。 最详细的方法是实例化 Label.FontSize 属性元素标记之间的 StaticExtension 类:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
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 命名空间声明:
xmlns:sys="clr-namespace:System;assembly=netstandard"
这可以让 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" />
最后一个示例显示 Device.RuntimePlatform 值。 Environment.NewLine 静态属性用于在两个 Span 对象之间插入一个新的换行符:
<Label HorizontalTextAlignment="Center"
FontSize="{x:Static local:AppConstants.NormalFontSize}">
<Label.FormattedText>
<FormattedString>
<Span Text="Runtime Platform: " />
<Span Text="{x:Static sys:Environment.NewLine}" />
<Span Text="{x:Static Device.RuntimePlatform}" />
</FormattedString>
</Label.FormattedText>
</Label>
下面是正在运行的示例:
x:Reference 标记扩展
ReferenceExtension 类支持 x:Reference 标记扩展。 该类具有 string 类型的名为 Name 的单一属性,可以将其设置为页面上已使用 x:Name 命名的元素的名称。 此 Name 属性是 ReferenceExtension 的内容属性,因此如果大括号中有 x:Reference,则不需要 Name=。
x:Reference 标记扩展专用于数据绑定,数据绑定一文对此进行了更详细的介绍。
“x:Reference 演示”页面显示了 x:Reference 在数据绑定中的两种用法,第一种是用于设置 Binding 对象的 Source 属性,第二种是用来设置两个数据绑定的 BindingContext 属性:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
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 Text="{Binding Source={x:Reference page},
StringFormat='The type of this page is {0}'}"
FontSize="18"
VerticalOptions="CenterAndExpand"
HorizontalTextAlignment="Center" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="Center" />
<Label BindingContext="{x:Reference slider}"
Text="{Binding Value, StringFormat='{0:F0}° rotation'}"
Rotation="{Binding Value}"
FontSize="24"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
两个 x:Reference 表达式都使用 ReferenceExtension 类名的缩写版本,并消除了表达式的 Name= 部分。 在第一个示例中,x:Reference 标记扩展嵌入到 Binding 标记扩展中。 注意,Source 和 StringFormat 设置用逗号分隔。 下面是正在运行的程序:
x:Type 标记扩展
x:Type 标记扩展是 C# typeof 关键字的 XAML 等效项。 它受 TypeExtension 类支持,该类定义了一个类型为 string 的名为 TypeName 的属性,该属性设置为类名或结构名。 x:Type 标记扩展返回该类或结构的 System.Type 对象。 TypeName 是 TypeExtension 的内容属性,因此 x:Type 与大括号一起出现时,不需要 TypeName=。
在 Xamarin.Forms 中,有几个属性具有类型为 Type 的参数。 示例包括 Style 的 TargetType 属性,以及用于在泛型类中指定参数的 x:TypeArguments 属性。 但是,XAML 分析程序会自动执行 typeof 操作,在这些情况下不会使用 x:Type 标记扩展。
需要的位置x:Type之一是标记x:Array扩展,下一部分将介绍。
x:Type 标记扩展在构造菜单时也很有用,在这种情况下,每个菜单项都对应特定类型的对象。 可以将 Type 对象与每个菜单项关联,然后在选中菜单项时实例化该对象。
这就是标记扩展程序中 MainPage 中的导航菜单的工作原理。 MainPage.xaml 文件包含 TableView,每个 TextCell 对应于程序中的特定页面:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MarkupExtensions"
x:Class="MarkupExtensions.MainPage"
Title="Markup Extensions"
Padding="10">
<TableView Intent="Menu">
<TableRoot>
<TableSection>
<TextCell Text="x:Static Demo"
Detail="Access constants or statics"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:StaticDemoPage}" />
<TextCell Text="x:Reference Demo"
Detail="Reference named elements on the page"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:ReferenceDemoPage}" />
<TextCell Text="x:Type Demo"
Detail="Associate a Button with a Type"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:TypeDemoPage}" />
<TextCell Text="x:Array Demo"
Detail="Use an array to fill a ListView"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:ArrayDemoPage}" />
···
</TableRoot>
</TableView>
</ContentPage>
下面是标记扩展中打开的主页:
每个 CommandParameter 属性都设置为引用其他页面之一的 x:Type 标记扩展。 每个 Command 属性都绑定到一个名为 NavigateCommand 的属性。 此属性在 MainPage 代码隐藏文件中定义:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
NavigateCommand = new Command<Type>(async (Type pageType) =>
{
Page page = (Page)Activator.CreateInstance(pageType);
await Navigation.PushAsync(page);
});
BindingContext = this;
}
public ICommand NavigateCommand { private set; get; }
}
NavigateCommand 属性是一个 Command 对象,它使用类型为 Type 的参数(CommandParameter 的值)实现执行命令。 该方法使用 Activator.CreateInstance 实例化页面,然后导航到该页。 构造函数最后将页面的 BindingContext 设置为自身,使得 Command 上的 Binding 可以正常工作。 请参阅数据绑定一文,特别是命令文章,了解有关此类代码的更多详细信息。
“x:Type 演示”页面使用类似的技术实例化 Xamarin.Forms 元素并将它们添加到 StackLayout。 XAML 文件最初由三个 Button 元素组成,它们的 Command 属性设置为 Binding,CommandParameter 属性设置为三个 Xamarin.Forms 视图的类型:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MarkupExtensions.TypeDemoPage"
Title="x:Type Demo">
<StackLayout x:Name="stackLayout"
Padding="10, 0">
<Button Text="Create a Slider"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Command="{Binding CreateCommand}"
CommandParameter="{x:Type Slider}" />
<Button Text="Create a Stepper"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Command="{Binding CreateCommand}"
CommandParameter="{x:Type Stepper}" />
<Button Text="Create a Switch"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Command="{Binding CreateCommand}"
CommandParameter="{x:Type Switch}" />
</StackLayout>
</ContentPage>
代码隐藏文件定义并初始化 CreateCommand 属性:
public partial class TypeDemoPage : ContentPage
{
public TypeDemoPage()
{
InitializeComponent();
CreateCommand = new Command<Type>((Type viewType) =>
{
View view = (View)Activator.CreateInstance(viewType);
view.VerticalOptions = LayoutOptions.CenterAndExpand;
stackLayout.Children.Add(view);
});
BindingContext = this;
}
public ICommand CreateCommand { private set; get; }
}
在按下 Button 时执行的方法会创建参数的新实例,设置其 VerticalOptions 属性,并将其添加到 StackLayout 中。 然后,这三个 Button 元素与动态创建的视图共享页面:
x:Array 标记扩展
通过 x:Array 标记扩展,可以在标记中定义数组。 ArrayExtension 类对其提供支持,该类定义两个属性:
Type类型的Type,表示数组中元素的类型。IList类型的Items,它是项本身的集合。 这是ArrayExtension的内容属性。
x:Array 标记扩展本身不会出现在大括号中。 但 x:Array 的开始标记和结束标记会分隔项列表。 将 Type 属性设置为 x:Type 标记扩展。
“x:Array 演示”页面显示了如何通过设置数组的 ItemsSource 属性来使用 x:Array 向 ListView 添加项:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
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>
<ViewCell>
<BoxView Color="{Binding}"
Margin="3" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
ViewCell 为每个颜色条目创建一个简单的 BoxView:
可通过多种方式指定此数组中的单个 Color 项。 可以使用 x:Static 标记扩展:
<x:Static Member="Color.Blue" />
或者,可使用 StaticResource 从资源字典中检索颜色:
<StaticResource Key="myColor" />
本文结束时,你将看到一个自定义 XAML 标记扩展,该扩展还会创建新的颜色值:
<local:HslColor H="0.5" S="1.0" L="0.5" />
定义常见类型的数组(如字符串或数字)时,请使用传递构造函数参数一文中列出的标记来分隔值。
x:Null 标记扩展
NullExtension 类支持 x:Null 标记扩展。 它没有属性,只是 C# null 关键字的 XAML 等效项。
x:Null 标记扩展很少需要,也很少使用,但如果确实需要它,你会庆幸有它。
“x:Null 演示”页面展示了一个场景,在该场景中 x:Null 可能很方便。 假设你为 Label 定义了一个隐式 Style,其中包含一个 Setter,它将 FontFamily 属性设置为与平台相关的系列名称:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MarkupExtensions.NullDemoPage"
Title="x:Null Demo">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="48" />
<Setter Property="FontFamily">
<Setter.Value>
<OnPlatform x:TypeArguments="x:String">
<On Platform="iOS" Value="Times New Roman" />
<On Platform="Android" Value="serif" />
<On Platform="UWP" Value="Times New Roman" />
</OnPlatform>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<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.Content>
</ContentPage>
然后你发现,对于其中一个 Label 元素,需要使用隐式 Style 中的所有属性设置,但 FontFamily 除外,你需要将其设置为默认值。 为此,可以另外定义一个 Style,但更简单的方法是将特定 Label 的 FontFamily 属性设置为 x:Null,如中间的 Label 所示。
下面是正在运行的程序:
注意,其中四个 Label 元素采用 serif 字体,但中间的 Label 元素采用默认的 sans-serif 字体。
OnPlatform 标记扩展
OnPlatform 标记扩展使你能够基于平台自定义 UI 外观。 它提供的功能与 OnPlatform 和 On 类相同,但表现形式更简洁。
OnPlatform 标记扩展由 OnPlatformExtension 类提供支持,该类定义以下属性:
object类型的Default,设置为默认值,以应用于表示平台的属性。object类型的Android,设置为在 Android 上应用的值。- 类型为
object的GTK,设置为要在 GTK 平台上应用的值。 object类型为iOS,设置为在 iOS 上应用的值。- 类型为
object的macOS,设置为要在 macOS 上应用的值。 object类型的Tizen,设置为在 Tizen 平台上应用的值。- 类型为
object的UWP,设置为要在通用 Windows 平台上应用的值。 - 类型为
object的WPF,设置为要在 Windows Presentation Foundation 平台上应用的值。 IValueConverter类型的Converter,可设置为IValueConverter实现。object类型的ConverterParameter,可设置为传递给IValueConverter实现的值。
注意
XAML 分析程序允许将 OnPlatformExtension 类缩写为 OnPlatform。
Default 属性是 OnPlatformExtension 的内容属性。 因此,对于用大括号表示的 XAML 标记表达式,可以删除此类表达式的 Default= 部分(前提是它是第一个参数)。 如果未设置 Default 属性,则默认为 BindableProperty.DefaultValue 属性值,前提是标记扩展名的目标是 BindableProperty。
重要说明
XAML 分析程序要求将正确类型的值提供给使用 OnPlatform 标记扩展的属性。 如果需要类型转换,OnPlatform 标记扩展将尝试使用 Xamarin.Forms 提供的默认转换器执行该转换。 但是,某些类型转换不能由默认转换器执行,在这些情况下,Converter 属性应设置为 IValueConverter 实现。
OnPlatform Demo 页显示如何使用 OnPlatform 标记扩展:
<BoxView Color="{OnPlatform Yellow, iOS=Red, Android=Green, UWP=Blue}"
WidthRequest="{OnPlatform 250, iOS=200, Android=300, UWP=400}"
HeightRequest="{OnPlatform 250, iOS=200, Android=300, UWP=400}"
HorizontalOptions="Center" />
在此示例中,所有三个 OnPlatform 表达式都使用 OnPlatformExtension 类名的简化版本。 三个 OnPlatform 标记扩展针对 iOS、Android 和 UWP 将 BoxView 的 Color、WidthRequest 和 HeightRequest 属性设置不同的值。 标记扩展还为未指定平台上的这些属性提供默认值,同时删除表达式的 Default= 部分。 请注意,设置的标记扩展属性用逗号分隔。
下面是正在运行的程序:
OnIdiom 标记扩展
通过 OnIdiom 标记扩展,可以根据运行应用程序的设备的惯用法来自定义 UI 外观。 它受定义以下属性的 OnIdiomExtension 类支持:
object类型的Default,设置为要应用于表示设备风格的属性的默认值。object类型的Phone,设置为要在手机上应用的值。object类型的Tablet,设置为要在平板电脑上应用的值。object类型的Desktop,设置为要在桌面平台上应用的值。object类型的TV,设置为要在电视平台上应用的值。object类型的Watch,设置为要在 Watch 平台上应用的值。IValueConverter类型的Converter,可设置为IValueConverter实现。object类型的ConverterParameter,可设置为传递给IValueConverter实现的值。
注意
XAML 分析程序允许将 OnIdiomExtension 类缩写为 OnIdiom。
Default 属性是 OnIdiomExtension 的内容属性。 因此,对于用大括号表示的 XAML 标记表达式,可以删除此类表达式的 Default= 部分(前提是它是第一个参数)。
重要说明
XAML 分析程序要求将正确类型的值提供给使用 OnIdiom 标记扩展的属性。 如果需要类型转换,OnIdiom 标记扩展将尝试使用 Xamarin.Forms 提供的默认转换器执行该转换。 但是,某些类型转换不能由默认转换器执行,在这些情况下,Converter 属性应设置为 IValueConverter 实现。
“OnIdiom 演示”页面显示了如何使用 OnIdiom 标记扩展:
<BoxView Color="{OnIdiom Yellow, Phone=Red, Tablet=Green, Desktop=Blue}"
WidthRequest="{OnIdiom 100, Phone=200, Tablet=300, Desktop=400}"
HeightRequest="{OnIdiom 100, Phone=200, Tablet=300, Desktop=400}"
HorizontalOptions="Center" />
在此示例中,所有三个 OnIdiom 表达式都使用 OnIdiomExtension 类名的简化版本。 这三个 OnIdiom 标记扩展会在手机、平板电脑和桌面惯例中将 BoxView 的 Color、WidthRequest 和 HeightRequest 属性设置为不同的值。 标记扩展还为未指定惯例中的这些属性提供默认值,同时删除表达式的 Default= 部分。 请注意,设置的标记扩展属性用逗号分隔。
下面是正在运行的程序:
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 应用程序的详细信息,请参阅 Xamarin.Forms Shell。
FontImage 标记扩展
FontImage 标记扩展支持在任何可以显示 ImageSource 的视图中显示字体图标。 它提供与 FontImageSource 类相同的功能,但具有更简洁的表示形式。
FontImage 标记扩展由 FontImageExtension 类提供支持,该类定义以下属性:
FontFamily,类型为string,是字体图标所属的字体系列。Glyph,类型为string,是字体图标的 unicode 字符值。Color,类型为Color,是显示字体图标时要使用的颜色。Size,类型为double,是呈现字体图标的大小(使用设备无关单位)。 默认值为 30。 此外,可以将此属性设置为命名字体大小。
注意
XAML 分析程序允许将 FontImageExtension 类缩写为 FontImage。
Glyph 属性是 FontImageExtension 的内容属性。 因此,对于用大括号表示的 XAML 标记表达式,可以删除此类表达式的 Glyph= 部分(前提是它是第一个参数)。
“FontImage 演示”页面显示了如何使用 FontImage 标记扩展:
<Image BackgroundColor="#D1D1D1"
Source="{FontImage , FontFamily={OnPlatform iOS=Ionicons, Android=ionicons.ttf#}, Size=44}" />
在本例中,FontImageExtension 类名的缩写版本用于在 Image 中显示来自 Ionicons 字体系列的 XBox 图标。 表达式还使用 OnPlatform 标记扩展在 iOS 和 Android 上指定不同的 FontFamily 属性值。 此外,表达式的 Glyph= 部分会被消除,设置的标记扩展属性用逗号分隔。 注意,虽然图标的 unicode 字符是 \uf30c,但它必须在 XAML 中转义,因此变为 。
下面是正在运行的程序:
有关通过在 FontImageSource 对象中指定字体图标数据来显示字体图标的信息,请参阅显示字体图标。
AppThemeBinding 标记扩展
AppThemeBinding 标记扩展使你能够根据当前系统主题指定要使用的资源,例如图像或颜色。
重要
AppThemeBinding 标记扩展具有最低操作系统要求。 有关详细信息,请参见响应 Xamarin.Forms 应用程序中的系统主题更改。
AppThemeBinding 标记扩展由 AppThemeBindingExtension 类提供支持,该类定义以下属性:
Default,类型为object,用户所设置的默认使用的资源。Light,类型为object,用户所设置的在设备使用其浅色主题时要使用的资源。Dark,类型为object,用户所设置的在设备使用其深色主题时要使用的资源。Value,类型为object,可返回标记扩展当前使用的资源。
注意
XAML 分析程序允许将 AppThemeBindingExtension 类缩写为 AppBindingTheme。
Default 属性是 AppThemeBindingExtension 的内容属性。 因此,对于用大括号表示的 XAML 标记表达式,可以删除此类表达式的 Default= 部分(前提是它是第一个参数)。
“AppThemeBinding 演示”页面显示了如何使用 AppThemeBinding 标记扩展:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MarkupExtensions.AppThemeBindingDemoPage"
Title="AppThemeBinding Demo">
<ContentPage.Resources>
<Style x:Key="labelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{AppThemeBinding Black, Light=Blue, Dark=Teal}" />
</Style>
</ContentPage.Resources>
<StackLayout Margin="20">
<Label Text="This text is green in light mode, and red in dark mode."
TextColor="{AppThemeBinding Light=Green, Dark=Red}" />
<Label Text="This text is black by default, blue in light mode, and teal in dark mode."
Style="{StaticResource labelStyle}" />
</StackLayout>
</ContentPage>
在此示例中,当设备使用其浅色主题时,Label 的文本颜色被设置为绿色,当设备使用其深色主题时,文本颜色被设置为红色。 第二个 Label 通过 Style 设置其 TextColor 属性。 默认情况下,此 Style 将 Label 的文本颜色设置为黑色,当设备使用浅色主题时设置为蓝色,在设备使用深色主题时设置为青色。
下面是正在运行的程序:

定义标记扩展
如果需要的 XAML 标记扩展在 Xamarin.Forms 中不可用,则可以创建自己的标记扩展。








