14.3 了解XAML
XAML(eXtensible Application Markup Language)是声明式语言,用于将构成XML的各个元素组成一个应用程序,而这些元素可用来表示一个结构化的.NET类集合。下面对XAML的概念进行详细介绍。
14.3.1 XAML简介
使用传统的显示技术时,要想从代码中分离出图形内容并不容易。对于Windows窗体应用程序关键问题是创建的每个窗体都是由C#代码定义的。当把控件拖动到设计器并配置控件时,VS会在相应的窗体类中自动调整代码。但是图形设计人员没有任何可以使用C#代码的工具。
相反,对于美工人员他们必须将工作内容导出为位图。然后可以使用这些位图确定窗体、按钮以及控件的外观。对于简单的固定用户界面这种方法还可行,但是在一些复杂布局界面中,将会变得非常麻烦和受限制。
而Silverlight通过XAML解决了这一问题。当在VS 2012中设计一个Silverlight应用程序时,窗口不会被转换为代码,而是转换为一系列的XAML标记。当运行应用程序时,这些标记用于生成构成用户界面的对象。
例如,要创建一个按钮则可以使用下面的XAML。
<Button HorizontalAlignment="Left" Margin="95,85,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1">我要登录</Button>
XAML中的元素名为CLR中的类名,上面的Button元素对应的是Silverlight中的Button类。XAML的属性是相应类中的属性,例如上面HorizontalAlignment、Margin和Width等实际上是Button类中对应的属性。上述代码中,还定义了事件处理程序“Click="Button_Click_1"”,表示触发按钮Click事件时执行Button_Click_1()方法,该方法在后台文件中进行了定义。
14.3.2 XAML语法规则
首先介绍一下XAML的基本语法规则,如下所示。
(1)在XAML中的所有元素都映射为一个.NET类的实例。元素的名称也完全对应于类名。例如,UserControl元素表示在WPF中创建一个System.Windows.Windows. UserControl对象。
(2)与所有XML文档一样,可以在一个元素中嵌套另一个元素。例如,在Grid元素中嵌套一个Button元素。
(3)可以通过属性设置每个类的特征。但是,在某些情况下属性不能实现时,则需要通过特殊的语法使用嵌套的标签。
接下来看一个XAML文档的基本框架,如下所示。为了便于说明,对每行代码都添加了行号。
1 <UserControl x:Class="SilverlightDemo.MainPage" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 mc:Ignorable="d" 7 d:DesignHeight="300" d:DesignWidth="400"> 8 <Grid x:Name="LayoutRoot" Background="White"> 9 </Grid> 10 </UserControl>
在这个文档中只包含两个元素,一个根级的UserControl元素和一个Gird元素。其中UserControl元素表示Silverlight应用程序的窗口,Grid元素表示一个容器,在该容器内可以放置其他控件。
与在所有XML文档中一样,在XAML文档中有且只能有一个根级元素。在上面示例中根元素为UserControl,在第10行使用</UserControl>标记结束了UserControl元素,此时文档也就结束了。也意味着在</UserControl>标记之后不允许有任何其他内容。
在第1行的UserControl元素开始标记中Class指定Silverlight程序对应的后台类名,第2行至第5行是4个XML命名空间。第7行定义了两个属性值,如下所示。
7 d:DesignHeight="300" d:DesignWidth="400">
表示的含义为当前Silverlight窗口的宽度为400像素,高度为300像素。
14.3.3 XAML命名空间
我们知道,XAML是从XML派生而来的。在XML中可以使用xmlns属性来定义命名空间,xmlns的全称是XML NameSpace。定义命名空间的好处是当来源不同的类重名时,可以使用命名空间来区分。
xmlns属性的语法格式如下。
xmlns[:可选映射前缀]="命名空间URL"
xmlns关键字后跟一个可选的映射前缀,之间用冒号分隔。如果没有设置映射前缀,那默认所有来自该命名空间的标记前都不用加前缀名,没有前缀名的命名空间也称为默认命名空间。一个XAML文档只能有一个默认命名空间,通常选择元素最频繁使用的命名空间作为默认。
例如,在14.3.2节的XAML文档代码中UserControl元素和Grid元素都来自第二行声明的默认命名空间。而第6行中的DesignHeight属性则来自d前缀引用的命名空间,该命名空间在第4行进行了定义。
【范例1】
对14.3.2节的XAML文档进行修改,将默认命名空间修改为m前缀,其他命名空间不变。修改后的代码如下。
<m:UserControl x:Class="SilverlightDemo.MainPage" xmlns:m="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <m:Grid x:Name="LayoutRoot" Background="White"> </m:Grid> </m:UserControl>
在上述代码中,第二行引用命名空间时指定了前缀为m,因此该命名空间下的UserControl元素和Grid元素应该使用m:UserControl和m:Grid进行标记。
在XAML中引用其他程序集和.NET命名空间的语法与C#是不一样的。在C#中,如果想使用System.Windows.Controls命名空间里的Button类,需要先把该命名空间所在的程序集通过添加引用的方式引用到项目中,然后在C#代码的顶部使用“using System.Windows.Controls;”语句引入该命名空间。在XAML中实现相同的功能也需要添加对程序集的引用,然后再到根元素的开始标记中通过如下语句进行引用。
xmlns:c="clr-namespace:System.Windows.Controls; assembly=PresentationFramework"
其中,c是命名空间的前缀,也可以是其他任意符合规范的名称。
命名空间URL并不是一个真实存在的URL地址,在这里只是XAML解析器的一个硬性编码,即看到这个URL就会引入一系列的程序集和程序集中包含的.NET命名空间。无论是程序集还是命名空间URL,用户都不需要去死记,因为VS 2012提供了强大的智能提示,如图14-7所示为输入“xmlns”之后的智能提示。
图14-7 VS 2012的程序集和命名空间智能提示
14.3.4 XAML后台文件
与ASP.NET一样,XAML也使用代码分离技术。一个Silverlight应用程序通常由两大部分组成,一部分是使用XAML描述UI元素在界面上的位置、大小等属性;另一部分是用来处理程序的逻辑、对传递事件的响应等操作。
在XAML中通过根元素的Class属性指定后台文件。例如,在MainPage.xaml文件中有代码“x:Class="SilverlightDemo.MainPage"”,此时VS 2012会自动创建一个后台文件MainPage.xaml.cs,并生成如下部分类代码。
namespace SilverlightDemo { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } } }
上述代码创建一个名为MainPage的类,该类继承是XAML中的UserControl基类。该类创建时使用partial关键字指定这是一个部分类。在该类中仅包含一个构造函数,构造函数又调用了InitializeComponent()方法。
InitializeComponent()方法在Silverlight应用程序中扮演着非常重要的角色。InitializeComponent()方法在源代码中是不可见的,因为它是在编译应用程序时自动生成的。本质上,InitializeComponent()方法的所有工作是调用System.Windows.Application类的LoadComponent()方法。LoadComponent()方法从程序集中提取编译过的XAML,并使它来构造用户界面。当解析XAML时,它会创建每个控件对象,设置其属性,并关联所有事件处理程序。
共有条评论 网友评论