第七章:XAML vs. code(4)

将XAML页面添加到您的项目

现在您已经看到了一些XAML片段,让我们看一个完整程序环境中的整个XAML页面。 首先,使用可移植类库解决方案模板创建一个名为CodePlusXaml的Xamarin.Forms解决方案。
现在将一个XAML ContentPage添加到PCL。 操作方法如下:在Visual Studio中,右键单击解决方案资源管理器中的CodePlusXaml项目。 从菜单中选择添加>新项目。 在Add New Item对话框中,选择左侧的Visual C#和Cross-Platform,以及中央列表中的Forms Xaml Page。 将其命名为CodePlusXamlPage.cs。
在Xamarin Studio中,调用解决方案列表中CodePlusXaml项目的下拉菜单,然后选择Add> New File。 在新建文件对话框中,选择左侧的表单和中央列表中的表单ContentPage Xaml。 (小心:列表中还有一个Forms ContentView Xaml,您需要一个内容页面。)将其命名为CodePlusXamlPage。
无论哪种情况,都会创建两个文件:

  • CodePlusXamlPage.xaml,XAML文件; 和
  • CodePlusXamlPage.xaml.cs,一个C#文件(尽管文件名是双奇数)。

在文件列表中,第二个文件在第一个文件的下面缩进,表示它们的密切关系。 C#文件通常被称为XAML文件的代码隐藏。 它包含支持标记的代码。 这两个文件都有助于派生自ContentPage的名为CodePlusXamlPage的类。
我们先来看一下代码文件。 不包括使用指令,它看起来像这样:

namespace CodePlusXaml
{
    public partial class CodePlusXamlPage : ContentPage
    {
        public CodePlusXamlPage()
        {
            InitializeComponent();
        }
    }
}

正如预期的那样,它确实是一个名为CodePlusXamlPage的类,它从ContentPage派生而来。 但是,类定义包含一个partial关键字,通常表明这只是CodePlusXamlPage类定义的一部分。 其他地方应该有另一个CodePlusXamlPage的分类定义。 所以如果它存在,它在哪里? 这是一个谜! (目前。)
另一个谜是构造函数调用的InitializeComponent方法。 仅仅从语法判断,似乎这个方法应该由ContentPage定义或继承。 但是,您不会在API文档中找到InitializeComponent。
我们暂时将这两个谜题放在一边,看看XAML文件。 Visual Studio和Xamarin Studio模板生成两个有点不同的XAML文件。 如果您使用的是Visual Studio,请删除标签的标记并将其替换为ContentPage.Content属性元素标记,以使其看起来像Xamarin Studio中的版本:


    
    

根元素是ContentPage,它是CodePlusXamlPage派生自的类。 该标签以两个XML名称空间声明开头,这两个声明都是URI。 但不要打扰检查网址! 那里什么都没有。 这些URI简单地表明谁拥有名称空间以及它所服务的功能。
默认名称空间属于Xamarin。 这是文件中没有前缀的元素(如ContentPage标记)的XML命名空间。 URI包括这个命名空间进入的年份,这个词形成Xamarin.Forms的缩写。
第二个命名空间按照约定与x的前缀相关联,并且它属于Microsoft。 该名称空间引用了XAML固有的元素和属性,并且可在每个XAML实现中找到。 单词winfx指的是曾经用于.NET Framework 3.0的名称,它引入了WPF和XAML。 2009年是指特定的XAML规范,这也意味着基于2006年的原始XAML规范的特定元素和属性集合。但是,Xamarin.Forms仅在2009年实现了元素和属性的子集 规范。
下一行是XAML固有的属性之一,称为Class。 由于x前缀几乎普遍用于此名称空间,因此此属性通常称为x:Class并声明为“x class”。
x:Class属性只能出现在XAML文件的根元素上。 它指定.NET名称空间和派生类的名称。 此派生类的基类是根元素。 换句话说,这个x:Class规范指出CodePlusXaml命名空间中的CodePlusXamlPage类派生自ContentPage。 这与CodePlusXamlPage.xaml.cs文件中的CodePlusXamlPage类定义完全相同。
让我们在XAML文件的这个ContentPage中添加一些内容。 这需要对Content属性进行设置,该属性在XAML文件中意味着在ContentPage.Confine属性元素标签之间添加内容。 使用StackLayout开始内容,然后将标签添加到Children属性中:


    
        
            
                
        
    

这就是你在本章开头看到的XAML标签。
您现在需要更改App类以实例化此页面,就像您使用ContentPage的代码衍生产品一样:

namespace CodePlusXaml
{
    public class App : Application
    {
        public App()
        {
            MainPage = new CodePlusXamlPage();
        }

     }
}

您现在可以构建和部署该程序。 在这样做之后,可以清除本节前面遇到的一些谜团:
在Visual Studio中,在解决方案资源管理器中,选择CodePlusXaml项目,在工具提示“显示所有文件”中找到顶部的图标,然后将其打开。
在Xamarin Studio中,在解决方案文件列表中,调用整个解决方案的下拉菜单,然后选择显示选项>显示所有文件。
在CodePlusXaml可移植类库项目中,找到obj文件夹,并在其中找到Debug文件夹。 您将看到一个名为CodePlusXamlPage.xaml.g.cs的文件。 注意文件名中的g。 这代表生成。 在这里,完整的评论告诉你这个文件是由一个工具生成的:

//------------------------------------------------------------------------------
// 
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// 
//------------------------------------------------------------------------------
namespace CodePlusXaml {
    using System;
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
 
    public partial class CodePlusXamlPage : global::Xamarin.Forms.ContentPage {
        [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
        private void InitializeComponent() {
             this.LoadFromXaml(typeof(CodePlusXamlPage));
        }
    }
}

在构建过程中,解析XAML文件,并生成此代码文件。 请注意,它是CodePlusXamlPage的部分类定义,它来自ContentPage,并且该类包含一个名为InitializeComponent的方法。
换句话说,它非常适合CodePlusXamlPage.xaml.cs代码隐藏文件。 生成CodePlusXamlPage.xaml.g.cs文件后,可以将这两个文件一起编译,就像它们只是普通的C#部分类定义一样。
在运行时,App类实例化CodePlusXamlPage类。 CodePlusXamlPage构造器(在代码隐藏文件中定义)调用InitializeComponent(在生成的文件中定义),InitializeComponent调用LoadFromXaml。 这是在Xamarin.Forms.Xaml程序集的Extensions类中定义的View的扩展方法。 LoadFromXaml的功能取决于你是否选择了编译XAML(如下一节所述)。 但是,当InitializeComponent方法返回时,整个页面就位,就好像所有东西都已经在CodePlusXamlPage构造函数中的代码中被实例化和初始化。
可以继续向代码隐藏文件的构造函数中的页面添加内容,但只能在InitializeComponent调用返回后才能添加内容。 让我们借此机会通过使用本章前面的一些代码创建另一个标签:

namespace CodePlusXaml
{
    public partial class CodePlusXamlPage : ContentPage
    {
        public CodePlusXamlPage()
        {
            InitializeComponent();
            Label label = 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
            };
            (Content as StackLayout).Children.Insert(0, label);
        }
    }
}

构造函数通过访问我们知道设置为页面的Content属性并在顶部插入Label的StackLayout来结束。 (在下一章中,通过使用x:Name属性,您将看到更好的方式来引用XAML文件中的对象。)可以在InitializeComponent调用之前创建Label,但不能将其添加到 当时的StackLayout是因为InitializeComponent是导致StackLayout(和所有其他XAML元素)被实例化的原因。 结果如下:
第七章:XAML vs. code(4)_第1张图片

除文本外,这两个按钮是相同的。
您不必花费太多时间检查XAML解析器创建的生成的代码文件,但了解XAML文件在生成过程和运行时间中的作用是很有帮助的。 此外,有时XAML文件中的错误会在LoadFromXaml调用中引发运行时异常,因此您可能会看到生成的代码文件经常弹出,您应该知道它是什么。

你可能感兴趣的:(第七章:XAML vs. code(4))