一个好老好老的老程序员了。
全部博文(915)
分类: Android平台
2018-06-23 20:42:29
属性和特性(估且叫特性吧)
这里是一个Xamarin.Forms标签在代码中实例化和初始化,就像它可能出现在页面类的构造函数中一样:
new Label { Text = "Hello from Code!", IsVisible = true, Opacity = 0.75, HorizontalTextAlignment = TextAlignment.Center, VerticalOptions = LayoutOptions.CenterAndExpand, TextColor = Color.Blue, BackgroundColor = Color.FromRgb(255, 128, 128), FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)), FontAttributes = FontAttributes.Bold | FontAttributes.Italic };
这是一个非常相似的标签,在XAML中实例化和初始化,您可以立即看到它比等效代码更简洁:
``` Xamarin.Forms类(如Label)将成为XAML中的XML元素。 诸如Text,IsVisible等属性在XAML中成为XML属性。 要在XAML中实例化,像Label这样的类必须有一个公共无参数的构造函数。 (在下一章中,您将看到有一种技术可以将参数传递给XAML中的构造函数,但通常用于特殊用途。)在XAML中设置的属性必须具有公共设置访问器。 按照惯例,空格围绕代码中的等号但不包含在XML(或XAML)中,但您可以根据需要使用尽可能多的空格。 XAML的简洁结果主要来自属性值的简洁 - 例如,使用单词“Large”而不是对Device.GetNamedSize方法的调用。 这些缩写不是内置到XAML分析器中的。 XAML解析器由专门为此定义的各种转换器类来辅助。 当XAML解析器遇到Label元素时,它可以使用反射来确定Xamarin.Forms是否具有名为Label的类,如果是,则可以实例化该类。 现在它已准备好将该对象初始化。 Text属性是字符串类型,属性值只是分配给该属性。 由于XAML是XML,因此可以使用标准XML语法在文本中包含Unicode字符。 在十进制Unicode值前加上&#(或者用十六进制Unicode值并且用&#x),然后用分号表示:
Text="Cost — ?123.45"
这些是em-dash和欧元符号的Unicode值。 要强制换行,请使用换行符&#x000A或(因为不需要前导零)&#xA,或者使用十进制&#10。 尖括号,&符号和引号在XML中有特殊含义,因此要将这些字符包含在文本字符串中,请使用以下标准预定义实体之一:
HTML预定义的实体,例如  不被支持。 对于不间断的空间,请改用 ; 另外,在第10章“XAML标记扩展”中,您会发现花括号({和})在XAML中有特殊含义。 如果您需要使用左花括号开始一个属性值,请使用一对花括号({}),然后左花括号开始。 回到示例:Label的IsVisible和Opacity属性的类型分别为bool和doubles,并且这些属性与您预期的一样简单。 XAML解析器使用Bool?ean.Parse和Double.Parse方法来转换属性值。 Boolean.Parse方法不区分大小写,但通常布尔值在XAML中被大写为“True”和“False”。 Double.Parse方法传递一个CultureInfo.InvariantCulture参数,所以转换不依赖于程序员或用户的本地文化。 Label的HorizontalTextAlignment属性是TextAlignment类型,它是一个枚举。 对于任何属于枚举类型的属性,XAML解析器使用Enum.Parse方法将字符串转换为值。 VerticalOptions属性是LayoutOptions类型的结构。 当XAML解析器使用反射引用LayoutOptions结构时,它会发现该结构具有定义的C#:
[TypeConverter (typeof(LayoutOptionsConverter))]
public struct LayoutOptions
{
…
}
(注意!这个讨论涉及两种类型的特性:XML特性,例如HorizontalText?Alignment和C#特性,例如TypeConverter。) TypeConverter特性由名为TypeConverterAttribute的类支持。 LayoutOptions上这个特殊的TypeConverter特性引用了一个名为LayoutOptionsConverter的类,该类来自一个名为TypeConverter的公共抽象类,该类定义了名为CanConvertFrom和ConvertFrom的方法。 当XAML解析器遇到此TypeConverter特性时,它将实例化LayoutOptionsConverter。 XAML中的VerticalOptions特性被分配了字符串“Center”,因此XAML解析器将该“Center”字符串传递给LayoutOptionsConverter的ConvertFrom方法,并弹出一个LayoutOptions值。 这被分配给Label对象的VerticalOptions属性。 同样,当XAML解析器遇到TextColor和BackgroundColor属性时,它将使用反射来确定这些属性的类型为Color。 Color结构也用TypeConverter特性进行装饰:
[TypeConverter (typeof(ColorTypeConverter))]
public struct Color
{
…
}
你可以创建一个ColorTypeConverter的实例,并在代码中进行实验。 它接受多种格式的颜色定义:它可以将诸如“Blue”的字符串转换为Color.Blue值,并将“Default”和“Accent”字符串转换为Color.Default和Color.Accent值。 Color?TypeConverter还可以解析编码红 - 绿 - 蓝值的字符串,如“#FF8080”,它是一个红色值为0xFF,绿色值为0x80,蓝色值也为0x80的值。 所有数字RGB值都以数字符号前缀开头,但该前缀后面可以跟随八位,六位,四位或三位十六进制数字,用于指定具有或不具有Alpha通道的颜色值。 这是最广泛的语法:
BackgroundColor="#aarrggbb"
每个字母代表一个十六进制数字,按照alpha(不透明度),红色,绿色和蓝色的顺序排列。 对于alpha通道,请记住0xFF是完全不透明的,0x00是完全透明的。 这里是没有Alpha通道的综合税:
BackgroundColor="#rrggbb"
在这种情况下,alpha值被设置为0xFF以获得完全不透明度。 其他两种格式允许您为每个通道只指定一个十六进制数字:
ackgroundColor="#argb"
BackgroundColor="#rgb"
在这些情况下,重复该数字以形成该值。 例如,#CF3是RGB颜色0xCC-0xFF-0x33。 这些短格式很少使用。 Label的FontSize属性的类型是double。 这与LayoutOptions和Color类型的属性有点不同。 LayoutOptions和Color结构是Xamarin.Forms的一部分,所以它们可以用C#TypeConverter属性标记,但不可能用TypeConverter属性标记.NET Double结构,仅用于字体大小! 相反,Label类中的FontSize属性具有TypeConverter特性:
public class Label : View, IFontElement
{
… [TypeConverter (typeof (FontSizeConverter))] public double FontSize { } …
}`
FontSizeConverter类确定传递给它的字符串是否是NamedSize枚举的成员之一。 如果不是,FontSizeConverter假定该值是双精度值。
示例中设置的最后一个属性是FontAttributes。 FontAttributes属性是名为FontAttributes的枚举,并且您已经知道XAML解析器会自动处理枚举类型。 但是,FontAttributes枚举具有如下所示的C#Flags特性集:
[Flags] public enum FontAttributes { None = 0, Bold = 1, Italic = 2 }
XAML解析器因此允许使用逗号分隔多个成员:
FontAttributes="Bold,Italic"
XAML解析器的机械性质的演示应该是非常好的消息。 这意味着您可以在XAML中包含自定义类,并且这些类可以具有自定义类型的属性,或者属性可以是标准类型,但允许其他值。 您所需要的只是使用C#TypeConverter特性标记这些类型或属性,并提供从TypeConverter派生的类。