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文件以下:html
< 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文件的结构:app
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也是在这个时候动态解析的。async
在项目的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方法里面。性能
动态加载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代码咱们同样能够动态加载,如:ui
// 一个透明度变化动画的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 片断”必需要符合如下要求:this
(1)XAML 内容字符串必须定义单个根元素,使用XamlReader.Load建立的内容只能赋予一个Windows Phone对象,它们是一对一的关系。spa
(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