Windows Phone 8初学者开发—第4部分:XAML简介

原文地址:web

http://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners/Part-4-Introduction-to-XAML架构

系列地址:http://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners编辑器

源代码: http://aka.ms/absbeginnerdevwp8 
PDF版本: http://aka.ms/absbeginnerdevwp8pdf函数

在本课中,我将讨论在第一课中编写的SoudBoard应用程序的XAML语法。但愿您注意到了咱们编写的XAML是如何影响手机预览窗格中咱们见到的内容。经过查看XAML来理解绝对基本的XAML是相对简单的,可是我想指出一些并不是一眼就能看出的特性和功能。布局

概要地讲本课的计划是:学习

  1. 咱们将经过与C#的比较来讨论XAML的目的和性质
  2. 咱们将讨论XAML的特殊特性,语言的一些隐藏功能,这些功能并不是看一眼就显而易见。

个人目标是:当本课结束时您将具有足够的理解咱们在本系列其他部分编写的XAML的知识,而且在我试图解释前就可以基本猜出它的做用。spa

1. XAML是什么?

在上一课我提到XAML的外观与HTML相似。这并不是偶然。XAML其实就是XML(可扩展标记语言the eXtensible Markup Language)。我待会儿会解释它们的关系,可是概要地讲,XML和HTML很是类似,它们具备共同的祖先。HTML用于构建web页面文档,而XML则更通用。此处“通用”的意思是您能够针对设想的任意用途来使用它,而且您能够定义元素和特性(attributes)的名称来知足您的须要。过去开发者利用XML来存储应用设置,在两个不一样的系统之间传输数据。为了使用XML,您须要定义架构(schema),它对元素和元素特性的名称进行声明。架构相似于一个合约(contract)。每一个人,无论他是XML的生产者仍是XML的使用者都遵照合约的规定以在相互间进行通信。所以架构是XML的重要组成部分。请记住上述分析,待会儿咱们还会对他进行讨论。设计

XAML是XML的一种特殊用法。很显然,咱们已经看到XAML与定义手机的用户界面有关。因此在这点上感受它很是像HTML。可是有一个很大的区别,XAML实际上用于建立类的实例和设置属性(properties)的值。例如,在前面的课程中咱们在XAML中定义了一个按钮:3d

上述代码大体等同于如下的C#代码:code

我已将上述C#代码添加到MainPage类的构造函数中。我待会儿会讨论MainPage.xaml和MainPage.xaml.cs之间的关系,可是咱们已经看到如何在MainPage.xaml.cs中经过编写程序方式的C#代码来定义行为。这里我仅仅编写了在MainPage类的新实例被建立时执行的代码(经过在类的构造函数中编写代码来实现)。

如今我有了两个按钮,一个以声明方式在XAML中定义、含有“内容Hello World”而且在单击按钮时会发出嘎嘎的叫声,另外一个是新建立的含有内容“Quack” 的按钮。当咱们运行应用:

咱们仅能看见一个按钮。那是由于我刚在C#中以程序方式(在MainPage类的构造函数中)建立的按钮位于咱们在上一课中在XAML中建立的按钮之上。我将加入一行C#代码用于设置新的Quack按钮的边距(margin),将它移动到靠左210像素的位置。

按钮的边距(Margin)属性是Thickness类型,它是一个通用用途的表明4个维度的类。在这里咱们建立了一个新的Thickness类并设置它的构造函数的第一个参数为210像素。当咱们再次运行应用:

咱们如今能够看到两个按钮。

更大的问题是咱们有了两个(几乎)相同的按钮,一个以声明方式在XAML中建立,另外一个以程序方式在C#中建立。

当我这样建立一个新的XAML元素时:

<Button></Button>

我基本上是在建立了一个新的按钮类的实例。

当我设置按钮元素的特性时,我基本上在设置按钮类实例的属性。

重要的是:XAML是建立类的实例和设置对象属性的一种更加简化和简洁的语法。用10行C#代码才能完成的工做只须要一行XAML。(即便在编辑器中我将它分红数行,它仍然比用C#建立对象的方法要简短得多)

此外,使用XAML我能够在手机预览窗格中迅速得到反馈。我当即能够看到更改的影响。在编写程序方式的C#代码时,当须要观察对代码的改动如何工做时我须要运行应用程序。

2. 类型转换器简介

若是您有敏锐的眼光,当遇到HorizontalAlignment特性时,您可能已经注意到XAML和C#版本的差别。若是您尝试:

myButton.HorizontalAlignment = “Left”;

将会产生一个编译错误。XAML分析器将经过值转换器来执行字符串“Left”到枚举值System.Windows.HorizontalAlignment.Left的转换。类型转换器是一个类,它能够将字符串值转换为强类型,Windows 8 API中有若干类型转换器,咱们会在这个系列中一直使用它们。在本例中的HorizontalAlignment属性,当被微软的开发人员开发时,在源代码中被一个特殊的特性标记,它指示XAML分析器经过类型转换器方法尝试将字符串“Left”匹配为枚举值System.Windows.HorizontalAlignment.Left。

当您试图拼错“Left”时,看看会发生什么:

 

您将会收到一个编译错误,由于类型转换器不能找到一个准确的匹配以转换为枚举值System.Windows.HorizontalAlignment.Left。

所以,XAML的第一个特色是:它是一种简洁的建立类的实例的手段。在构建Windows 8应用时,它被用来建立用户界面元素的实例,可是XAML不只仅是一项用户界面技术,它能够在其余技术中用于其余目的。

3. 理解XMAL命名空间声明

接下来,让咱们讨论MainPage.xaml文件顶部的代码,咱们在以前一直没有涉及到它。

在文件顶部咱们看到如下内容:

当您在查看上述内容时,回忆一下我刚才说的—有关架构属于XML的一部分。若是确实如此,那么XAML在哪里保证遵照架构?

观察第3行至第8行。MainPage.xaml须要保证遵照六个架构。每个都经过xmlns特性来定义。在第3行定义的第一个xmlns是缺省的命名空间,换句话说没有冒号和冒号后的单词,就像你在第4行至第8行看到的那样。

第4行至第8行的其他命名空间使用名称/冒号的组合。所以,须要说明的是:x 或:phone是与架构(咱们将其称为合约)相关的命名空间。MainPage.xaml其他部分的每一个元素或特性必须遵照至少这些架构中的一个,不然文档就是无效的。换句话说,若是XAML中的元素或特性没有在这些命名空间中定义,那么就不能保证编译器(即分析源代码并建立可执行文件的程序)在手机上运行,编译器将没法理解如何执行特定的指令。

所以,在本例中:

<Grid x:Name="LayoutRoot" Background="Transparent">

 

咱们将指望Grid元素和Background特性是缺省架构的一部分,缺省架构对应第3行定义的缺省命名空间。

可是,x:Name是对应第4行定义的x:命名空间的架构的一部分。

我有一个好主意,让咱们首先定位到缺省的命名空间以了解更多有关命名空间的构成:

http://schemas.microsoft.com/winfx/2006/xaml/presentation

 

什么?!架构在该URL实际上并不存在!在这个意义上讲,架构并无在该URL发布并能够查看。相反,架构只是一个惟一的名称,相似于咱们在C#中使用命名空间识别两个具备相同名称的类。架构(所以,在XAML中的命名空间)使得类名称能够被排序,有点相似于姓氏和名字。该URL,或更恰当地说咱们应该认为它是URI(Uniform Resource IDENTIFIER 统一资源标示符,而不是Locator 定位器),被用做命名空间的标示符。XML命名空间是对各种应用程序分析XAML的指令。Windows运行时XAML分析器将努力把它变成可执行代码,而Visual Studio和Blend设计器将努力把它变成设计时的体验。

所以,第二个XML命名空间定义了一个映射,x:属于该架构。

http://schemas.microsoft.com/winfx/2006/xaml

 

所以,任何前面带有x:前缀的元素或特性名称意味着他们遵照第二个架构。

可是区别在哪里?差异很小,可是第二个架构定义了XAML的内在规则。第一个架构定义了Windows 8对XAML特定使用方面的合约/规则。换句话说,咱们能够不须要前缀而使用Grid, Button, MediaElement 和其余Windows Phone 8 XAML元素的事实意味着他们定义于缺省的命名空间中。

第5和第6行为Phone(手机)和Shell(界面)定义了命名空间和架构,他们位于不一样的URI,注意Microsoft.Phone CLR(是Common Language Runtime的缩写,即通用语言运行时)命名空间提供的线索,定义他们的程序集在安装Windows Phone 8 API后被安装在咱们的计算机上。

您能够看到,第一行:

<phone:PhoneApplicationPage

 

代表PhoneApplicationPage类自己就是定义的一部分。PhoneApplicationPage从Windows.System.Controls.Page派生,它刚好也是Windows Presentation Foundation页面类和Windows应用商店应用程序页面类的父类。它含有不少被全部三种项目类型共享的基本功能。因此好处是您能够利用在本系列中学到的内容建立WPF桌面应用和Windows应用商店应用。固然会有一些差别,可是也有不少共同点。

第7行和第8行定义用于容许Visual Studio左侧的手机预览窗格正常显示的命名空间和架构。这些指令在运行时将被忽略,这也是第9行须要完成的工做—当编译XAML代码时,忽略任何为:d的前缀。

好,我知道还有一些问题并未给出答案。咱们能够花更多时间讨论细节,可是重要的是在每一个添加到手机项目中的XAML文件顶部的代码是有目的的,它定义了XAML代码必须遵照的规则。您几乎不须要修改这些代码,可是若是您将它们删除,您可能就会中断您的应用程序。因此我以为除非有充足的理由,不然不要改动它。在第10行至14行还有一些额外的内容,咱们将在本系列的之后课程中讨论。

4. 理解.xaml和xaml.cs文件之间的关系

在Visual Studio的解决方案设计器中,您将看到XAML文件有一个箭头,它意味着咱们能够展开它们以显示具备相同名称的C#文件,惟一的区别是它在结尾处包含一个.cs的文件扩展名。若是查看.cs版本的文件,您将发现它定义了一个MainPage类,此外它定义了一个分部类(partial class):

另外一半在MainPage.xaml的第1和第2行中定义:

<phone:PhoneApplicationPage
x:Class="SoundBoard.MainPage"

...

 

虽然他没有使用Partial这一术语(不一样于程序方式的对应部分),但他确实代表了两者之间的关系。

为何重要?这种关系意味着编译器将把MainPage.xaml 和MainPage.xaml.cs的输出合并到单个类中。这意味着他们是总体的两个组成部分。这是一个重要的概念,XAML被编译为中间语言就像C#被编译为中间语言同样而且他们都是单个类的部分实现。能够这么说,这使您能够在一个文件中建立类的实例,而后在另外一个文件中使用它。这就是容许我在XAML中建立一个名称为_audioPlayer 的MediaElement类的实例而且在C#中调用它的方法和属性的缘由。稍后咱们将在本课中看到更多这样的例子。

5. 理解缺省属性

由于XAML本质上是XML文档,咱们能够在其余元素内嵌入元素。咱们已经看过这种状况的一个例子。

<PhoneApplicationPage>
    <Grid ...>
        <Grid ... >
            <MediaElement ... />
            <Button ... />
        </Grid>
    </Grid>
</PhoneApplicationPage>
    

 

或者,也许在XAML术语中更准确的说法是用户控件(UserControl)的Content属性被设置为Grid,

这里PhoneApplicationPage“包含”一个Grid,而且Grid“包含”一个MediaElement和一个Button。

而且Grid的子集合(Children collection)包括MediaElement 和Button。根据您正在使用的控件

类型,缺省属性可使用嵌入样式的语法被填充。因此您能够这样作:

<Button Content="Hello World" ... />

 

或者这样

<Button ... >
    Hello World
</Button>

 

由于Content属性是Button类的缺省属性。

6. 理解复杂属性和属性元素语法

在某些状况下,仅仅设置特性值隐藏了后台如何运做的复杂性。一个很好的例子就是设置Background=”Red”。在C#中咱们已经见过这个程序,它用于完成相同的事情:

myButton.Background = newSolidColorBrush(Colors.Red);

 

咱们须要建立一个新的SolidColorBrush实例并传递一个枚举颜色值。这是另外一个很好的有关属性类型转换器的例子,咱们在较早前已经学习过了。可是有些特性太复杂以致于没法表示为特性。

当属性(property)不可以简单地表示为XAML特性(attribute)时,它被称为“复杂属性”。为了演示它,首先我将从按钮中删除Background="Red"特性,删除缺省属性"Hello World!",并用特性Content="Quack"从新添加 :

 

接着,在属性窗格我将Background属性设置为线性渐变画笔。

  1. 选择画笔(Brush)属性以显示画笔编辑器。
  2. 确认选择了背景(Background)。
  3. 选择渐变画笔标签(中间的标签)。
  4. 移动选择器至颜色编辑器的右上角。

我将在手机预览窗格看到如下内容:

可是更重要的是:让咱们查看画笔编辑器生成的XAML。

用于建立背景的XAML不能简单地像之前使用单词”Red”那样用一个简单的字符串进行设置。相反,请注意Backgound属性被转变为按钮的自身元素:

<Button ... >
    <Button.Background>
    ...
     </Button.Background>
</Button>

这被称为“属性元素”语法,而且形式为<Control.Property>。

一个很好的例子是线性渐变画笔(LinearGradientBrush)。术语“画笔 (Brush)”意味着咱们正在处理一个表示单个颜色(或多个颜色)的对象。将“画笔”理解为颜料刷,这个特殊的颜料刷将建立一个线性的渐变,颜色将从上到下或从左到右进行改变。固然,您实际上不会去作此处代码所作的工做,由于它与Windows Phone 8应用程序的审美标准相悖。可是假设如今咱们须要经过使用渐变颜色做为按钮的背景颜色来表达咱们的个性。

您能够看到(以下图),若是咱们须要定义一个线性渐变画笔,咱们须要提供不少信息以呈现正确的画笔。例如何时应该进入下一个颜色。线性渐变画笔包含一组GradientStop对象,它们定义了渐变中的颜色和颜色的位置。

然而,在上面的代码段中表明LinearGradientBrush的XAML实际由Visual Studio自动进行了缩短。这是未缩短的格式:

    <Button.Background>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <LinearGradientBrush.GradientStops>
                <GradientStopCollection>
                    <GradientStop Color="Red" Offset="1" />
                    <GradientStop Color="Black" Offset="0" />
                </GradientStopCollection>
            </LinearGradientBrush.GradientStops>
        </LinearGradientBrush>
    </Button.Background>

 

 

注意<LinearGradientBrush.GradientStops>和<GradientStopCollection>元素是如何被省略的。这样作是为了简洁和紧凑,而且能够被智能化的分析器识别。首先GradientStops属性是LinearGradientBrush的缺省属性。其次GradientStops是GradientStopCollection类型并实现了IList<T>,此处T是GradientStop类型。有鉴于此,XAML分析器能够推断惟一能够被嵌套在<LinearGradientBrush ... />中的是一个或多个GradientBrush的实例,每个被隐式地添加到GradientStopCollection中。

 

所以故事的寓意是XAML容许咱们以声明方式建立类的实例,而且在设计用户界面元素时能够进行精细的控制。即使如此,XAML分析器是智能化的,只要有足够的信息正确地建立对象图(object graph)时,它就不须要咱们包含冗余的代码。

 

回顾

 

综上所述,咱们已经学习了XAML的语法。大部分XAML很是简单,但也有一些并不是显而易见的内容:

 

  1. XAML是XML的一个实现,并在很大程度上依赖架构和命名空间以遵照“合约”的要求,这样不一样应用程序就能够建立、解释、显示或编译XAML代码。
  2. XAML的目的是用紧凑、简洁的语法建立类的实例并设置它们的属性。咱们对在C#中经过程序方式建立按钮和在XAML中以声明方式建立按钮进行了比较,而且看到后者须要的代码更少。
  3. 因为它的内置功能(好比类型转换器,它容许将简单的字符串转换成类的实例),XAML须要的代码更少。
  4. 对于更复杂的属性设置,XAML提供属性元素语法,它利用智能的XAML分析器并依赖默认属性进行推断以减小用于表达设计的XAML代码的数量。
  5. 咱们了解了嵌入式语法风格和嵌入式元素的性质,它们代表了视觉元素之间的关系。例如PhoneApplicationPage包含一个用于布局的Grid,它又包含输入或其余类型的控件。它们用表示包含或所属关系的开始和结束元素来表示。
  6. 咱们了解了缺省属性,每一个控件含有一个缺省的属性,可使用与嵌入式语法相同的样式对缺省属性进行设置。

 

接下来,让咱们学习更多有关网格的布局的内容,咱们还将在下一课学习XAML的附加属性语法和如何链接事件。

相关文章
相关标签/搜索