XAML编译器
您可以选择是否在构建过程中编译XAML。 编译XAML可以在构建过程中进行有效性检查,减少可执行文件的大小,并缩短加载时间,但这比非编译方法稍微新一些,所以有时可能会出现问题。
为了表明您想要编译应用程序中的所有XAML文件,可以在代码文件中的某个位置插入下面的程序集属性。 最方便的地方是PCL项目的Properties文件夹中的Assembly.cs文件:
[assembly: XamlCompilation(XamlCompilationOptions.Compile
你可以把它放在另一个C#文件中,但是因为它是一个程序集属性,它需要位于任何名称空间块之外。 您还需要Xamarin.Forms.Xaml的使用指令。
您也可以指定编译特定类的XAML文件:
namespace CodePlusXaml
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CodePlusXamlPage : ContentPage
{
public CodePlusXamlPage()
{
InitializeComponent();
}
}
}
XamlCompilationOptions枚举有两个成员Compile和Skip,这意味着您可以使用XamlCompilation作为程序集属性来为项目中的所有类使用XAML编译,但可以跳过使用Skip成员的单个类的XAML编译。
如果您不选择编译XAML,则整个XAML文件将作为嵌入资源绑定到可执行文件中,就像第4章中BlackCat程序中的Edgar Allan Poe故事一样。实践中,您可以访问XAML 文件在运行时通过使用GetManifestResourceStream方法。 这与在InitializeComponent中调用的LoadFromXaml类似。 它加载XAML文件并第二次解析它,实例化并初始化XAML文件中除根元素(已存在)以外的所有元素。
当你选择编译XAML时,这个过程有点简化,但LoadFrom?Xaml方法仍然需要实例化所有元素并构建一个可视化树。
XAML文件中的平台特异性
这是一个名为ScaryColorList的程序的XAML文件,它类似于您之前看到的XAML代码片段。 但是现在重复更加可怕,因为每个颜色项目都被一个Frame包围:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScaryColorList.ScaryColorListPage">
<ContentPage.Content>
<StackLayout>
<StackLayout.Children>
<Frame OutlineColor="Accent">
<Frame.Content>
<StackLayout Orientation="Horizontal">
<StackLayout.Children>
<BoxView Color="Red" />
<Label Text="Red"
VerticalOptions="Center" />
</StackLayout.Children>
</StackLayout>
</Frame.Content>
</Frame>
<Frame OutlineColor="Accent">
<Frame.Content>
<StackLayout Orientation="Horizontal">
<StackLayout.Children>
<BoxView Color="Green" />
<Label Text="Green"
VerticalOptions="Center" />
</StackLayout.Children>
</StackLayout>
</Frame.Content>
</Frame>
<Frame OutlineColor="Accent">
<Frame.Content>
<StackLayout Orientation="Horizontal">
<StackLayout.Children>
<BoxView Color="Blue" />
<Label Text="Blue"
VerticalOptions="Center" />
</StackLayout.Children>
</StackLayout>
</Frame.Content>
</Frame>
</StackLayout.Children>
</StackLayout>
</ContentPage.Content>
</ContentPage>
代码隐藏文件仅包含对InitializeComponent的标准调用。
除了重复的标记之外,该程序还有一个更实际的问题:当它在iOS上运行时,顶部项与状态栏重叠。 这个问题可以通过在页面构造函数中调用Device.OnPlatform来解决(就像你在第2章中看到的那样)。 因为Device.OnPlatform在页面上设置了Padding属性,并且不需要XAML文件中的任何内容,所以它可以在InitializeComponent调用之前或之后进行。 以下是一种方法:
public partial class ScaryColorListPage : ContentPage
{
public ScaryColorListPage()
{
Padding = Device.OnPlatform(new Thickness(0, 20, 0, 0),
new Thickness(0),
new Thickness(0));
InitializeComponent();
}
}
或者,您可以在XAML文件的根元素中为所有三个平台设置统一的Padding值:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScaryColorList.ScaryColorListPage"
Padding="0, 20, 0, 0">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
这为页面设置了Padding属性。 ThicknessTypeConverter类需要用逗号分隔值,但与厚度构造函数相比,您具有相同的灵活性。 您可以按照左侧,顶部,右侧和底部的顺序指定四个值; 两个值(左边和右边的第一个,第二个顶部和底部); 或一个值。
但是,您也可以使用OnPlatform类在XAML文件中指定特定于平台的值,其名称暗示它在功能上类似于Device.OnPlatform静态方法。
OnPlatform是一个非常有趣的课程,值得深入了解它的工作原理。 这个类是通用的,它有三个T类型的属性,以及一个将它自己转换为T的隐式转换,它使用Device.OS值:
public class OnPlatform<T>
{
public T iOS { get; set; }
public T Android { get; set; }
public T WinPhone { get; set; }
public static implicit operator T(OnPlatform<T> onPlatform)
{
// returns one of the three properties based on Device.OS
}
}
理论上,您可以在代码中使用OnPlatform 类,也许在ContentPage派生的构造函数中使用这个类:
Padding = new OnPlatform<Thickness>
{
iOS = new Thickness(0, 20, 0, 0),
Android = new Thickness(0),
WinPhone = new Thickness(0)
};
您可以将此OnPlatform类的实例直接设置为Padding属性,因为On?Platform类定义了将其自身转换为泛型参数(本例中为Thickness)的隐式转换。
但是,您不应该在代码中使用OnPlatform。 改用Device.OnPlatform。 OnPlatform是为XAML设计的,唯一非常棘手的部分是弄清楚如何指定泛型类型参数。
幸运的是,XAML 2009规范包含一个专门为通用类设计的属性,称为TypeArguments。 因为它是XAML本身的一部分,所以它与x前缀一起使用,所以它显示为x:TypeArguments。 以下是XAML中如何使用OnPlatform在三个厚度值中进行选择的方法:
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0"
Android="0"
WinPhone="0" />
在这个例子中(和前面的代码示例),Android和WinPhone设置不需要,因为它们是默认设置。 请注意,Thickness字符串可以直接设置为属性,因为这些属性的类型是Thickness,因此XAML分析器将使用ThicknessTypeConverter来转换这些字符串。
现在我们有了OnPlatform标记,我们如何将它设置为Page的Padding属性? 当然,通过使用property-element语法来表达Padding!
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ScaryColorList.ScaryColorListPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
这就是ScaryColorList程序如何出现在本书示例集合中,以下是它的外观:
与OnDevice类似,OnIdiom区分手机和平板电脑。 由于在下一章中将会出现的原因,您应该尝试将OnDevice和OnIdiom的使用限制为小块标记而不是大块。 它们的使用不应成为XAML文件中的结构元素。