访问静态成员
IMarkupExtension最简单和最有用的实现之一封装在StaticExtension类中。 这是原始XAML规范的一部分,因此它通常出现在带有x前缀的XAML中。 StaticExtension定义了一个名为Member of string的属性,您可以将其设置为公共常量,静态属性,静态字段或枚举成员的类和成员名称。
让我们看看它是如何工作的。 这是一个标签,其中六个属性设置为通常在XAML中显示的属性:
<Label Text="Just some text"
BackgroundColor="Accent"
TextColor="Black"
FontAttributes="Italic"
VerticalOptions="Center"
HorizontalTextAlignment="Center" />
其中五个属性设置为最终引用各种静态属性,字段和枚举成员的文本字符串,但这些文本字符串的转换通过类型转换器和枚举类型的标准XAML解析进行。
如果您希望更明确地将这些属性设置为各种静态属性,字段和枚举成员,则可以在属性元素标记中使用x:StaticExtension:
<Label Text="Just some text">
<Label.BackgroundColor>
<x:StaticExtension Member="Color.Accent" />
</Label.BackgroundColor>
<Label.TextColor>
<x:StaticExtension Member="Color.Black" />
</Label.TextColor>
<Label.FontAttributes>
<x:StaticExtension Member="FontAttributes.Italic" />
</Label.FontAttributes>
<Label.VerticalOptions>
<x:StaticExtension Member="LayoutOptions.Center" />
</Label.VerticalOptions>
<Label.HorizontalTextAlignment>
<x:StaticExtension Member="TextAlignment.Center" />
</Label.HorizontalTextAlignment>
</Label>
Color.Accent是一个静态属性。 Color.Black和LayoutOptions.Center是静态字段。 FontAttributes.Italic和TextAlignment.Center是枚举成员。
考虑到使用文本字符串设置这些属性的难易程度,使用Stat?icExtension的方法最初看起来很荒谬,但请注意它是一种通用机制。 如果StaticExtension标记的类型与target属性的类型匹配,则可以使用StaticExtension标记中的任何静态属性,字段或枚举成员。
按照惯例,实现IMarkupExtension的类在其名称中包含单词Extension,但您可以将其保留在XAML中,这就是为什么此标记扩展通常称为x:Static而不是x:StaticExtension。 以下标记略微短于前一个块:
<Label Text="Just some text">
<Label.BackgroundColor>
<x:Static Member="Color.Accent" />
</Label.BackgroundColor>
<Label.TextColor>
<x:Static Member="Color.Black" />
</Label.TextColor>
<Label.FontAttributes>
<x:Static Member="FontAttributes.Italic" />
</Label.FontAttributes>
<Label.VerticalOptions>
<x:Static Member="LayoutOptions.Center" />
</Label.VerticalOptions>
<Label.HorizontalTextAlignment>
<x:Static Member="TextAlignment.Center" />
</Label.HorizontalTextAlignment>
</Label>
现在,对于真正重大的主要 - 语法的改变导致属性元素标签消失,占用空间大大缩小。 XAML标记扩展几乎与标记扩展名和一对花括号中的参数一起出现:
<Label Text="Just some text"
BackgroundColor="{x:Static Member=Color.Accent}"
TextColor="{x:Static Member=Color.Black}"
FontAttributes="{x:Static Member=FontAttributes.Italic}"
VerticalOptions="{x:Static Member=LayoutOptions.Center}"
HorizontalTextAlignment="{x:Static Member=TextAlignment.Center}" />
这种带有花括号的语法无处不在地与XAML标记扩展一起使用,许多开发人员认为标记扩展与大括号语法同义。 这几乎是正确的:虽然花括号总是表示存在XAML标记扩展,但在许多情况下,标记扩展可以在没有花括号的XAML中出现(如前所示),并且有时可以方便地使用它们。
staticExtension类的operty不再是XML属性。 就XML而言,由花括号分隔的整个表达式是属性的值,并且花括号内的参数不带引号。
就像元素一样,标记扩展可以具有ContentProperty属性。 仅具有一个属性的标记扩展(例如具有单个成员属性的StaticExtension类)始终将该唯一属性标记为内容属性。 对于使用卷括号语法的标记扩展,这意味着可以删除成员属性名称和等号:
<Label Text="Just some text"
BackgroundColor="{x:Static Color.Accent}"
TextColor="{x:Static Color.Black}"
FontAttributes="{x:Static FontAttributes.Italic}"
VerticalOptions="{x:Static LayoutOptions.Center}"
HorizontalTextAlignment="{x:Static TextAlignment.Center}" />
这是x:Static标记扩展的常见形式。
显然,不需要对这些特定属性使用x:Static,但是您可以定义自己的静态成员来实现应用程序范围的常量,并且可以在XAML文件中引用它们。 这在SharedStatics项目中得到了证明。
SharedStatics项目包含一个名为AppConstants的类,它定义了一些可能用于格式化文本的常量和静态字段:
namespace SharedStatics
{
static class AppConstants
{
public static Color LightBackground = Color.Yellow;
public static Color DarkForeground = Color.Blue;
public static double NormalFontSize = 18;
public static double TitleFontSize = 1.4 * NormalFontSize;
public static double ParagraphSpacing = 10;
public const FontAttributes Emphasis = FontAttributes.Italic;
public const FontAttributes TitleAttribute = FontAttributes.Bold;
public const TextAlignment TitleAlignment = TextAlignment.Center;
}
}
如果每个平台需要不同的东西,可以在这些定义中使用Device.OnPlatform。
然后,XAML文件使用18 x:静态标记扩展来引用这些项。 请注意将本地前缀与项目命名空间相关联的XML名称空间声明:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SharedStatics"
x:Class="SharedStatics.SharedStaticsPage"
BackgroundColor="{x:Static local:AppConstants.LightBackground}">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<StackLayout Padding="10, 0"
Spacing="{x:Static local:AppConstants.ParagraphSpacing}">
<Label Text="The SharedStatics Program"
TextColor="{x:Static local:AppConstants.DarkForeground}"
FontSize="{x:Static local:AppConstants.TitleFontSize}"
FontAttributes="{x:Static local:AppConstants.TitleAttribute}"
HorizontalTextAlignment="{x:Static local:AppConstants.TitleAlignment}" />
<Label TextColor="{x:Static local:AppConstants.DarkForeground}"
FontSize="{x:Static local:AppConstants.NormalFontSize}">
<Label.FormattedText>
<FormattedString>
<Span Text="Through use of the " />
<Span Text="x:Static"
FontSize="{x:Static local:AppConstants.NormalFontSize}"
FontAttributes="{x:Static local:AppConstants.Emphasis}" />
<Span Text=
" XAML markup extension, an application can maintain a collection of
common property settings defined as constants, static properties or fields,
or enumeration members in a separate code file. These can then be
referenced within the XAML file." />
</FormattedString>
</Label.FormattedText>
</Label>
<Label TextColor="{x:Static local:AppConstants.DarkForeground}"
FontSize="{x:Static local:AppConstants.NormalFontSize}">
<Label.FormattedText>
<FormattedString>
<Span Text=
"However, this is not the only technique to share property settings.
You'll soon discover that you can store objects in a " />
<Span Text="ResourceDictionary"
FontSize="{x:Static local:AppConstants.NormalFontSize}"
FontAttributes="{x:Static local:AppConstants.Emphasis}" />
<Span Text=" and access them through the " />
<Span Text="StaticResource"
FontSize="{x:Static local:AppConstants.NormalFontSize}"
FontAttributes="{x:Static local:AppConstants.Emphasis}" />
<Span Text=
" markup extension, and even encapsultate multiple property settings in a " />
<Span Text="Style"
FontSize="{x:Static local:AppConstants.NormalFontSize}"
FontAttributes="{x:Static local:AppConstants.Emphasis}" />
<Span Text=" object." />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ContentPage>
具有FontAttributes设置的每个Span对象都会重复在Label本身上设置的FontSize设置,因为当应用其他与字体相关的设置时,Span对象不会从Label继承与字体相关的设置。
这是:
此技术允许您在多个页面上使用这些公共属性设置,如果您需要更改值,则只需更改AppSettings文件。
也可以使用x:Static和静态属性以及在外部li?braries中的类中定义的字段。 下面的示例名为SystemStatics,它设计得非常合适 - 它将Button的BorderWidth设置为等于Math类中定义的PI静态字段,并使用静态Environment.New?Line属性来处理文本中的换行符。 但它证明了这项技术。
Math和Environment类都在.NET System命名空间中定义,因此需要新的XML命名空间声明来定义名为(例如)sys for System的前缀。 请注意,此命名空间声明将CLR命名空间指定为System,但将程序集指定为mscorlib,它最初代表Microsoft公共对象运行时库,但现在代表多语言标准公共对象运行时库:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="SystemStatics.SystemStaticsPage">
<StackLayout>
<Button Text=" Button with π border width "
BorderWidth="{x:Static sys:Math.PI}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Button.BackgroundColor>
<OnPlatform x:TypeArguments="Color"
Android="#404040" />
</Button.BackgroundColor>
<Button.BorderColor>
<OnPlatform x:TypeArguments="Color"
Android="White"
WinPhone="Black" />
</Button.BorderColor>
</Button>
<Label VerticalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
FontSize="Medium">
<Label.FormattedText>
<FormattedString>
<Span Text="Three lines of text" />
<Span Text="{x:Static sys:Environment.NewLine}" />
<Span Text="separated by" />
<Span Text="{x:Static sys:Environment.NewLine}" />
<Span Text="Environment.NewLine"
FontSize="Medium"
FontAttributes="Italic" />
<Span Text=" strings" />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ContentPage>
除非设置了背景颜色,否则按钮边框不会显示在Android中,并且在An?droid和Windows Phone上边框都需要非默认颜色,因此一些额外的标记可以解决这些问题。 在iOS平台上,按钮边框往往会挤压按钮文本,因此文本在开头和结尾都定义了空格。
仅从视觉效果来判断,我们必须相信按钮边框宽度约为3.14单位宽,但断线肯定有效:
使用花括号进行标记扩展意味着您无法显示由花括号括起来的文本。 本文中的花括号将被误认为是标记扩展名:
<Label Text="{Text in curly braces}" />
那不行。 您可以在文本字符串中的其他位置使用花括号,但不能以左大括号开头。
但是,如果确实需要,可以通过使用由左右一对花括号组成的转义序列开始文本,确保文本不会被误认为是XAML标记扩展:
<Label Text="{}{Text in curly braces}" />
这将显示您想要的文本。