1.1.2 XAML页面的编译

Windows Phone的应用程序项目会通过Visual Studio完成XAML页面的编译,在程序运行时会通过直接链接操作加载和解析XAML,将XAML和过程式代码自动连接起来。如果你不在乎将XAML文件和过程式代码融合,那么只需要把它添加到Visual Studio的Windows Phone项目中来,并用界面中的Build动作来完成编译即可,一般公共的样式资源的XAML文件都是采用这种方式。但是如果要编译一个XAML文件并将它与过程式代码混合,第一步要做的就是为XAML文件的根元素指定一个子类,可以用XAML语言命名空间中的Class关键字来完成,一般Windows Phone的程序页面是采用这种方式,通常在Windows Phone项目新增的XAML文件都会自动地生成一个对应的XAML.CS文件,并且默认地将两个文件关联起来,例如,添加的XAML文件如下:

    < Page
x:Class="PhoneApp1.MainPage"
……>
……省略若干代码
</ Page>

与XAML文件关联起来的XAML.CS文件如下:

namespace PhoneApp1
{
public sealed partial class MainPage : Page
{
……省略若干代码
}
}

通常我们把与XAML文件关联的XAML.CS文件叫作代码隐藏文件。如果你引用XAML中的任何一个事件处理程序(通过事件特性,如Button的Click特性),这里就是我们定义这些事件处理程序的地方。类定义中的partial关键字很重要,因为类的实现是分布在多个文件中的。可能你会觉得奇怪,因为在项目里面只看到了MainPage.xaml.cs文件定义了MainPage类,其实MainPage类还在另外一个地方定义了,只是在项目工程里面隐藏了而已。当我们编译完Windows Phone的项目时,你会在项目的obj\Debug文件夹下看到Visual Studio创建的以g.cs为扩展名的文件,对于每一个XAML文件,你会找到对应有一个g.cs文件。例如,如果我们项目中有一个MainPage.xaml文件,你就会在obj\Debug文件夹下找到MainPage.g.cs文件。下面来看一下MainPage.g.cs文件的结构:

using System;
……
namespace PhoneApp1 {
public partial class MainPage : global::Windows.UI.Xaml.Controls.Page {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
(global::Windows.UI.Xaml.Controls.Grid LayoutRoot;
……
private bool _contentLoaded;
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
global::Windows.UI.Xaml.Application.LoadComponent(this, new global::System.Uri("ms-appx:///MainPage.xaml"), global::Windows.UI.Xaml.Controls.Primitives.ComponentResourceLocation.Application);
LayoutRoot = (global::Windows.UI.Xaml.Controls. Grid)this.FindName("LayoutRoot");
……
}
}
}

从MainPage.g.cs文件中我们可以看到,MainPage类在这里还定义了一些控件和相关的方法,并且InitializeComponent()方法里面加载和解析了MainPage.xaml文件MainPage.cs文件里面的MainPage()方面里面调用的InitializeComponent()方法就是在MainPage.g.cs文件里面定义的。在xaml页面中声明的控件,通常会在.g.cs中生成对应控件的内部字段。实际上这取决于控件是否有x:Name属性,只要有这个属性,都会自动调用FindName方法,用于把字段和页面控件关联。没有x:Name属性,则没有字段,这种关联会有一定的性能浪费,因为是在应用载入控件的时候,通过LoadComponents方法关联的,而xaml也是在这个时候动态解析的。

在项目的obj\Debug文件夹下,我们还找到了g.i.cs为扩展名的文件,对于每一个XAML文件,你也会找到对应有一个g.i.cs文件,并且这些g.i.cs文件与对应的g.cs文件是基本一样的。那么这些g.i.cs文件又有怎样的含义呢?其实这些g.i.cs文件并不是在编译的时候生成的,而是当你创建了XAML文件的时候就马上生成,或者你修改了XAML文件g.i.cs文件也会跟着改变,而g.cs文件则是必须要成功编译了项目之后才会生成的。文件后缀中的g表示generated产生的意思,i表示intellisense智能感知的意思,g.i.cs文件是XAML文件对应的智能感知文件,在vs中利用go to definition功能找InitializeComponent方法的实现的时候,进入的就是g.i.cs文件的InitializeComponent方法里面。

1.1.3 动态加载XAML

动态加载XAML是指在程序运行时通过解析XAML格式的字符串或者文件来动态生成UI的效果。通常情况下,Windows Phone的界面元素都是通过直接读取XAML文件的内容来呈现的,如上一小节讲解的那样通过XAML文件和XAML.CS文件关联起来编译,这也是默认的UI实现的方式,但是在某些时候你并不能预先设计好所有的XAML元素,而是需要在程序运行的过程中动态地加载XAML对象,那么这时候就需要使用到动态加载XAML来实现了。

在应用程序里面动态加载XAML需要使用到XamlReader.Load方法来实现,XamlReader 类是为分析 XAML 和创建相应的 Windows Phone 对象树提供 XAML 处理器引擎,XamlReader.Load 方法可以分析格式良好的 XAML 片段并创建相应的 Windows Phone对象树,然后返回该对象树的根。大部分可以再XAML页面上编写的代码,我们都可以通过动态加载XAML的形式来实现,不仅仅是普通的UI控件,动画等其他的XAML代码我们一样可以动态加载,如:

        // 一个透明度变化动画的XAML代码的字符串
private const string FadeInStoryboard =
@"<Storyboard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
<DoubleAnimation
Duration=""0:0:0.2""
Storyboard.TargetProperty=""(UIElement.Opacity)""
To=""1""/>
</Storyboard>";
//使用XamlReader.Load方法加载XAML字符串并且解析成动画对象
Storyboard storyboard = XamlReader.Load(FadeInStoryboard) as Storyboard;

使用 XamlReader.Load方法动态加载XAML对XAML的字符串是有一定的要求的,那么这些“格式良好的 XAML 片段”必须要符合以下要求:

(1)XAML 内容字符串必须定义单个根元素,使用XamlReader.Load创建的内容只能赋予一个Windows Phone对象,它们是一对一的关系。

(2)内容字符串 XAML 必须是格式良好的 XML,并且必须是可分析 XAML。

(3)所需的根元素还必须指定某一默认的 XML 命名空间值。这通常是命名空间 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"。

下面给出动态加载XAML的示例: 演示了使用XamlReader.Load方法加载XAML字符串生成一个按钮和加载XAML文件生成一个矩形。
    代码清单1-1动态加载XAML(源代码:第1章\Examples_1_1)

MainPage.xaml文件主要代码
------------------------------------------------------------------------------------------------------------------
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel x:Name="sp_show">
<Button x:Name="bt_addXAML" Content="加载XAML按钮" Click="bt_addXAML_Click"></Button>
</StackPanel>
</Grid>
Rectangle.xaml文件代码:被动态加载到程序里面去的XAML文件
------------------------------------------------------------------------------------------------------------------
<Rectangle xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="200" Width="480">
<Rectangle.Fill>
<LinearGradientBrush>
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Red" Offset="0.5"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush >
</Rectangle.Fill>
</Rectangle>
MainPage.xaml.cs文件主要代码
------------------------------------------------------------------------------------------------------------------
// 加载XAML按钮
private void bt_addXAML_Click(object sender, RoutedEventArgs e)
{
//注意XAML字符串里面的命名空间"http://schemas.microsoft.com/winfx/2006/xaml/presentation" 不能少。
string buttonXAML = "<Button xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' " +
" Content=\"加载XAML文件\" Foreground=\"Red\"></Button>";
Button btnRed = (Button)XamlReader.Load(buttonXAML);
btnRed.Click += btnRed_Click;
sp_show.Children.Add(btnRed);
}
// 已加载的XAML按钮关联的事件
async void btnRed_Click(object sender, RoutedEventArgs e)
{
string xaml = string.Empty;
//加载程序的Rectangle.xaml文件
StorageFile fileRead = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("Rectangle.xaml");
// 读取文件的内容
xaml = await FileIO.ReadTextAsync(fileRead);
// 加载Rectangle
Rectangle rectangle = (Rectangle)XamlReader.Load(xaml);
sp_show.Children.Add(rectangle);
}

本文来源于《深入理解Windows Phone 8.1 UI控件编程》

源代码下载:http://vdisk.weibo.com/s/zt_pyrfNHoezI

欢迎关注我的微博@WP林政

WP8.1技术交流群:372552293

[WP8.1UI控件编程]Windows Phone XAML页面的编译的更多相关文章

  1. [WP8.1UI控件编程]Windows Phone大数据量网络图片列表的异步加载和内存优化

    11.2.4 大数据量网络图片列表的异步加载和内存优化 虚拟化技术可以让Windows Phone上的大数据量列表不必担心会一次性加载所有的数据,保证了UI的流程性.对于虚拟化的技术,我们不仅仅只是依 ...

  2. [WP8.1UI控件编程]Windows Phone VirtualizingStackPanel、ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件

    11.2.2 VirtualizingStackPanel.ItemsStackPanel和ItemsWrapGrid虚拟化排列布局控件 VirtualizingStackPanel.ItemsSta ...

  3. [WP8.1UI控件编程]Windows Phone动画方案的选择

    8.1 动画方案的选择 Windows Phone的动画实现方式有线性插值动画(3种类型).关键祯动画(4种类型)和基于帧动画,甚至还有定时器动画,然后动画所改变的UI元素属性可以是普通的UI元素属性 ...

  4. [WP8.1UI控件编程]Windows Phone理解和运用ItemTemplate、ContentTemplate和DataTemplate

    2.2.5 ItemTemplate.ContentTemplate和DataTemplate 在理解ItemTemplate.ContentTemplate和DataTemplate的关系的之前,我 ...

  5. [WP8.1UI控件编程]Windows Phone自定义布局规则

    3.2 自定义布局规则 上一节介绍了Windows Phone的系统布局面板和布局系统的相关原理,那么系统的布局面板并不一定会满足所有的你想要实现的布局规律,如果有一些特殊的布局规律,系统的布局面板是 ...

  6. [WP8.1UI控件编程]SemanticZoom控件实现分组列表

    11.1.5 SemanticZoom实现分组列表 SemanticZoom控件可以让用户实现一种更加高级的列表,这种列表可以对列表的项目进行分组,同时这个SemanticZoom控件会提供两个具有相 ...

  7. 《深入理解Windows Phone 8.1 UI控件编程》基于最新的Runtime框架

    <深入理解Windows Phone 8.1 UI控件编程>本书基于最新的Windows Phone 8.1 Runtime SDK编写,全面深入地论述了最酷的UI编程技术:实现复杂炫酷的 ...

  8. 如何添加地图控件到Windows Phone 8的页面中

    原文 如何添加地图控件到Windows Phone 8的页面中 本主题介绍了各种方法来添加一个地图控件到Windows Phone 8的项目.该地图控件在Windows Phone的SDK 8.0的库 ...

  9. MFC控件编程之 按钮编辑框.静态文本的使用,以及访问控件的七种方法.

    MFC控件编程之 按钮编辑框.静态文本的使用以及访问控件的七种方法. 一丶按钮.静态文本的通用属性. 他们都有一个属性.就是可以输入标题内容.以及可以自定义控件ID. 创建一个MFC Dlg对话框. ...

随机推荐

  1. macosx安装MySQLdb

    折腾了半天,记录一下. 先按照这个步骤安装mysql-python 如果python setup.py install 时候出现clang 错误,运行 python -E setup.py insta ...

  2. golang debug with LiteIDE

    golang 的调试比较麻烦,debug stop into 无法跳转到自己写的代码,但是能够跳转到系统提供的代码. 以下是简单的测试代码: package main import ( "f ...

  3. SublimeText 插件

    Markdown 预览 想要预览,可以配置下面的快捷方式. { "keys": ["alt+m"], "command": "ma ...

  4. [Tools] Eclipse使用小技巧-持续更新

    [背景] 使用之中发现一些eclipse使用的小技巧,记录下来供以后查阅   Eclipse保存preferences,并导入到其他workspaces The Export wizard can b ...

  5. [荐]js模版引擎handlebars.js

    [官方介绍:http://handlebarsjs.com/] Handlebars provides the power necessary to let you build semantic te ...

  6. Eclipse调试方法及快捷键

    基本操作 断点,breakpoint: F5键与F6键均为单步调试: F5是step into,也就是进入本行代码中执行,跳入 F6是step over,跳过,也就是执行本行代码,跳到下一行 F7是跳 ...

  7. android:imeOptions属性(转)

    默认情况下软键盘右下角的按钮为“下一个”,点击会到下一个输入框,保持软键盘 设置 android:imeOptions="actionDone" ,软键盘下方变成“完成”,点击后光 ...

  8. 【项目经验】——JSON.parse() && JSON.stringify()

    我们在做项目的时候,都知道序列化和反序列化,师哥说:"有正就有反,有来就有回!"的确,就是这样.然后我们在这里分享一下JSON.stringify()  和JSON.parse() ...

  9. struts2框架快速入门小案例

    struts2快速入门: index.jsp------>HelloAction--------->hello.jsp struts2流程 1.导入jar包 struts2的目录结构: a ...

  10. 在C#程序中实现插件架构

    阅读提示:这篇文章将讲述如何利用C#奇妙的特性,实现插件架构,用插件(plug-ins)机制建立可扩展的解决方案. 在.NET框架下的C#语言,和其他.NET语言一样提供了很多强大的特性和机制.其中一 ...