第七章:XAML vs. code(5)

简介:

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程序如何出现在本书示例集合中,以下是它的外观:
201806262141270342

与OnDevice类似,OnIdiom区分手机和平板电脑。 由于在下一章中将会出现的原因,您应该尝试将OnDevice和OnIdiom的使用限制为小块标记而不是大块。 它们的使用不应成为XAML文件中的结构元素。

目录
相关文章
|
6月前
|
存储 测试技术 UED
Qt中实现界面回放的艺术:从理论到代码“ (“The Art of Implementing UI Playback in Qt: From Theory to Code
Qt中实现界面回放的艺术:从理论到代码“ (“The Art of Implementing UI Playback in Qt: From Theory to Code
144 1
|
前端开发 C# 数据格式
WPF中任意Object的XAML代码格式化输出
原文:WPF中任意Object的XAML代码格式化输出 有时候,我们需要将WPF中的控件自身的XAML代码输出成文本,那么,我们可以使用System.Windows.Markup.XamlWriter.Save()方法来完成此任务。
911 0
|
C# Windows
在WPF中,如何得到任何Object对象的XAML代码?
原文:在WPF中,如何得到任何Object对象的XAML代码? 在WPF中,可以使用System.Windows.Markup.XamlWriter.Save(objName)得到任何Object对象的XAML代码。
814 0
|
JavaScript Android开发 索引
第八章:代码和XAML协调一致5
点按手势 Xamarin.Forms按钮响应手指点击,但您实际上可以从任何派生自View的类中获取手指点击,包括Label,BoxView和Frame。 这些点击事件不会内置到View类中,但View类会定义名为GestureRecognizers的属性。
1326 0
|
JavaScript Android开发
|
XML JavaScript Android开发
|
XML JavaScript C#
第七章:XAML vs. code(3)
属性元素语法这里有一些C#与第4章中的FramedText代码相似。在一个语句中,它实例化一个Frame和一个Label,并将Label设置为Frame的Content属性: new Frame { OutlineColor = Color.
910 0
|
JavaScript Android开发 iOS开发