代码文件和XAML文件始终作为一对存在。 这两个文件相互补充。 尽管被称为XAML的“代码隐藏”文件,但代码在处理应用程序的更活跃和交互式部分时经常显得尤为突出。 这意味着代码隐藏文件必须能够像在代码中实例化的对象一样轻松地引用XAML中定义的元素。 同样,XAML中的元素必须能够触发在基于代码的事件处理程序中处理的事件。 这就是本章的全部内容。
但首先,我们来探索一些用于在XAML文件中实例化对象的不寻常技术。
传递参数
当您运行包含XAML文件的应用程序时,XAML文件中的每个元素都会通过调用相应类或结构的无参数构造函数来实例化。 加载过程通过设置属性值的属性来继续初始化结果对象。 这似乎很有道理。 但是,使用XAML的开发人员有时需要使用需要参数的构造函数或通过调用静态创建方法来实例化对象。 这些需求通常不涉及API本身,而是涉及XAML文件引用的与API交互的外部数据类。
2009年的XAML规范引入了一个x:Arguments元素和一个x:FactoryMethod来表达这些情况,而Xamarin.Forms支持它们。 这些技术通常不会在一般情况下使用,但您应该看看它们在需要时如何工作。
带参数的构造函数
要将参数传递给XAML中元素的构造函数,元素必须分隔为开始标签和结束标签。 使用x:Arguments开始和结束标签跟随元素的开始标记。 在那些x:Arguments标记内,包含一个或多个构造函数参数。
但是,如何指定常见类型的多个参数,例如double或int? 你用逗号分析参数吗?
不。每个参数必须用开始和结束标记分隔。 幸运的是,XAML 2009规范定义了常用基本类型的XML元素。 您可以使用这些标签来阐明元素的类型,在OnPlatform中指定泛型类型,或者分隔构造函数参数。 这是Xamarin.Forms支持的完整集合。 注意它们复制.NET类型名称而不是C#类型名称:
x:Object
x:Boolean
x:Byte
x:Int16
x:Int32
x:Int64
x:Single
x:Double
x:Decimal
x:Char
x:String
x:TimeSpan
x:Array
x:DateTime (由Xamarin.Forms支持,但不是XAML 2009规范)
你会很难找到所有这些的用途,但你一定会发现其中一些用途。
ParameteredConstructorDemo示例演示了如何使用x:Arguments,其中包含由x:Double标签分隔的参数,使用Color结构的三个不同构造函数。 具有三个参数的结构需要红色,绿色和蓝色值,范围从0到1.带有四个参数的构造函数添加一个alpha通道作为第四个参数(在此设置为0.5),以及带有a的构造函数 单参数表示从0(黑色)到1(白色)的灰色阴影:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ParameteredConstructorDemo.ParameteredConstructorDemoPage">
<StackLayout>
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<BoxView.Color>
<Color>
<x:Arguments>
<x:Double>1</x:Double>
<x:Double>0</x:Double>
<x:Double>0</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<BoxView.Color>
<Color>
<x:Arguments>
<x:Double>0</x:Double>
<x:Double>0</x:Double>
<x:Double>1</x:Double>
<x:Double>0.5</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<BoxView.Color>
<Color>
<x:Arguments>
<x:Double>0.5</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
</StackLayout>
</ContentPage>
x:Arguments标签中的元素数量以及这些元素的类型必须与类或结构的构造函数之一匹配。 这是结果:
蓝色的BoxView在浅色背景下是浅色的,在深色背景下是暗色的,因为它透明度为50%,让背景显示出来。
我可以从XAML调用方法吗?
有一次,这个问题的答案是“不要太荒谬”,但现在它是一个合格的“是”。不过,不要太激动。 您可以在XAML中调用的唯一方法是返回与定义方法的类(或结构)相同类型的对象(或值)的方法。 这些方法必须是公共的和静态的。 它们有时被称为创建方法或工厂方法。 您可以通过使用x:FactoryMethod属性及其使用x:Arguments元素的参数指定方法名称,通过调用其中一个方法来实例化XAML中的元素。
Color结构定义了七个返回Color值的静态方法,所以这些方法是合格的。 这个XAML文件使用了其中的三个:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FactoryMethodDemo.FactoryMethodDemoPage">
<StackLayout>
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<BoxView.Color>
<Color x:FactoryMethod="FromRgb">
<x:Arguments>
<x:Int32>255</x:Int32>
<x:Int32>0</x:Int32>
<x:Int32>0</x:Int32>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<BoxView.Color>
<Color x:FactoryMethod="FromRgb">
<x:Arguments>
<x:Double>0</x:Double>
<x:Double>1.0</x:Double>
<x:Double>0</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<BoxView.Color>
<Color x:FactoryMethod="FromHsla">
<x:Arguments>
<x:Double>0.67</x:Double>
<x:Double>1.0</x:Double>
<x:Double>0.5</x:Double>
<x:Double>1.0</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
</StackLayout>
</ContentPage>
这里调用的前两个静态方法都被命名为Color.FromRgb,但是x:Arguments标签中的元素类型区分了范围从0到255的int参数和范围从0到1的双参数。第三个 是Color.FromHsla方法,它根据色调,饱和度,亮度和alpha分量创建一个Color值。 有趣的是,这是通过使用Xamarin.Forms API从XAML文件中的HSL值定义Color值的唯一方法。 这是结果: