[Windows8 app store开发系列教程二] XAML(2)

  上一篇博文我简单的介绍了一下xaml的概况,下面我将讲解一下具体的语法

元素和特性

  XAML规范定义了一些规则,用于把.NET命名空间、类型、属性和事件映射为XML命名空间、元素和特性。以下面为例,它定义了一个win8的按钮,跟另一段与之功能一致的C#代码比较一下(上一篇博文里):

下面定义了一个win8应用的按钮:

  XAML:

<Button Content="Button" HorizontalAlignment="Left" Margin="152,87,0,0" VerticalAlignment="Top" Width="75"/>

  C#

Button b = new Button();
b.Content = "OK";
b.Click += new RoutedEventHandler(button_Click);
grid.Children.Add(b);//grid是Grid控件的name,这句话是用来把动态生成的button键显示在grid上

  虽然这两段代码功能是相同的,但如果去除掉XAML中的Click特性,你可以很快地在vs中查看XAML,还会看到一个活生生的按钮放在设计器中。而C#代码则必须要额外的代码编译方可使用。也就是说在XAML中定义一个元素(叫作对象元素)与在.NET中实例化一个对应的对象(总是使用默认的构造函数)是等价的。设置对象元素的一个特性(attribute),与设置一个同名属性(property attribute,称为属性特性)或者为一个同名事件设置一个事件处理程序(也称为事件特性),也是等价的。

生成和事件处理的顺序

  在运行时(run-time)模式下,为任何一个XAML声明的对象设置属性之前,总要添加一些事件处理程序,这样就可以让某个事件在属性被设置时被触发,而不用担心XAML使用特性的顺序。

  至于多个属性集或添加多个事件处理程序,它们总会遵照一定顺序,即属性特性和事件属性是在对象元素中指定的。这一排序方式不会在实际应用中产生影响,因为.NET设计指南指出:类应该允许以任何顺序设置属性,添加事件处理程序也是如此。

命名空间

  

比较上述XAML代码示例和相应的C#代码示例,最神秘的地方在于XAML命名空间("http://schemas.microsoft.com/winfx/2006/xaml/presentation")是如何被映射到.NET命名空间(Windows.UI.Xaml.Controls;)上的。该映射及其他win8命名空间的映射是在win8程序集中硬编码完成的。

  XAML文件的根对象元素属性指定至少一个XML命名空间,用于验证自己和子元素。你可以(在根元素或子元素上)声明额外的XML命名空间,但每一个命名空间下的标识符都必须有一个唯一的前缀。例如,win8应用的XAML文件都会使用第二个命名空间加上前缀x(记作xmlns:x而不仅仅是xmlns):

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  这是XAML语言命名空间,用于映射System.Windows.Markup命名空间中的类型,而且它也定义了XAML编译器或解析器中的一些特殊的指令。这些指令通常是作为XAML元素的特性出现的,因此,它们看上去像宿主元素的属性,但实际上并不是如此。

  我们把http://schemas.microfost.com/winfx/2006/xaml/presentation作为默认(主要)命名空间,把xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"作为次要命名空间。次要命名空间的前缀是x,这仅仅是一个规则,就像C#文件要以using System;指令开始一样。

属性元素

  富创建是xaml的亮点之一,我们可以用Button来演示。你可以把任意内容放在Button里面,不仅限于文本,如下所示(在Button中嵌入了一个图片来做一个图片按钮):

<Button HorizontalAlignment="Left" Margin="539,118,0,0" VerticalAlignment="Top">
            <Button.Content>
                <Image Source="oureda.png" Height="100" ></Image>
            </Button.Content>
</Button>

效果图如下:

当然正如我们所说,还可以使用c#编写后台代码达到相同的效果:

Image i = new Image();
i.Height = 100;
Button b = new Button();
i.Source = new BitmapImage(new Uri("ms-appx:///oureda.png"));
b.Content = i;
grid.Children.Add(b);

  Content属性被设置为一个XML元素而不是XML特性,Button.Content中的句点用于区分对象元素(object element)与属性元素(property element)。它们总会以“类型名,属性名TypeName.PropertyName”的形式出现,总会包含在“类型名”对象元素中,但它们没有属于自己的特性。

  属性元素语法也可以用于简单的属性值。下面的Button使用特性设置了两个属性,它们是Content和Background:

 <Button Content="Button" Background="Yellow"/>

  这等同于使用元素设置该Button的两个相同的属性:

<Button>
  <Button.Content>
    
OK   </Button.Content>   <Button.Background>
    Yellow
  </Button.Background>
</Button>

类型转换器

  上例XAML文件中的“Yellow”是如何转化到C#中的Windows.UI.Xaml.Media.Brush类型的呢?这个示例提供了一些如何使用字符串设置XAML属性的细节,这些属性的类型即不是System.String,也不是System.Object。在这种情况下,XAML解析器或编译器必须寻找一个类型转换器,该转换器知道如何将一个字符串表达式转换为一种想要的数据类型。WPF提供了许多常用数据类型的类型转换器,如Brush、Color、FontWeight、Point等,它们都派生自Type-Converter的类(如BrushConverter、ColorConverter等),你也可以为自定义的数据类型写类型转换器。与XAML语言不同,类型转换器通常支持不区分大小写的字符串。

  如果没有Brush类型转换器,你就必须使用属性元素语法来设置XAML中的Background属性,如下所示:

<Button.Background>
    <SolidColorBrush>
    <SolidColorBrush.Color>
        <Color A="255" R="255" G="255" B="0"/>
    </SolidColorBrush.Color>
    </SolidColorBrush>
</Button.Background>

对象元素的子元素

  XAML文件就像所有的XML文件一样,必须有一个单独的根对象元素。对象元素是可以支持子对象元素的。一个对象元素可以有3种类型的子元素:一个内容属性值,集合项,或一个能够通过类型转换到它的父元素的值。

内容属性

  大多数xaml(通过定制特性)指定了一个属性,该属性可以被设置为XML元素中的任何内容。这个属性叫作内容属性,它确实是一个让XAML呈现变得更轻便简单的捷径。从某种意义上讲,这些内容属性有点像VB中的默认属性。Button中的Content属性就是这样指定的,如:

<Button Content="OK"/>

可以被重写为:

<Button >
OK
</Button>

还有更复杂的方式:

<Button>
  <Button.Content>
      <Rectangle Height="40" Width="40" Fill="Black"/>
  </Button.Content>
</Button>

可以被重写为:

<Button>
    <Rectangle Height="40" Width="40" Fill="Black"/>
</Button>

(注:这里需要注意一下,笔者测试win8应用里只有button的Content可以默认不写,其余控件都需要添加)

集合项

  XAML允许将项添加到支持索引的两种类型的集合中:List和Dictionary。

  List是实现了System.Collection.IList接口的集合,如System.Collections.ArrayList和许多win8应用的集合类都是List。如,下面的XAML向ListBox添加了两个项,它的Items属性是实现了IList的ItemCollection类型:

  

<ListBox > 
    <ListBox.Items>
         <ListBoxItem Content="Item 1"/>
         <ListBoxItem Content="Item 2"/> 
    </ListBox.Items> 
</ListBox>

  System.Windows.ResourceDictionary是win8应用中的一个常用的集合类型,它实现了System.Collections.IDictionary接口,能够支持在过程式代码中添加、移除枚举键/值对。下面的XAML添加了两个Color对象到一个ResourceDictionary中。

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Color x:Key="1" A="255" R="255" G="255" B="255"/>
    <Color x:Key="2" A="0" R="0" G="0" B="0"/>
</ResourceDictionary>

注意,在带有x:Key的XAML中指定的值总是被作为字符串处理的,除非使用标记扩展,但不会尝试使用类型转换。

  为了避免混淆,在转换子元素时,任何一个有效的XAML解析器或编译器必须遵循下面的规则:

  1. 如果该类型实现了IList接口,就为每个子元素调用IList.Add。
  2. 否则,如果该类型实现了IDictionary,就为每个子元素调用IDictionary.Add,在该值的键和元素中使用x:Key特性值。
  3. 否则,如果父元素支持内容属性(由System.Windows.Markup.ContentPropertyAttribute表示),而且子元素的类型与该内容属性是兼容的,就把子元素作为它的值。
  4. 否则,如果子对象是普通文本,且有类型转换器将子对象转换为父类型(没有在父元素上设置属性),则把子元素作为类型转换器的输入,将输出作为父对象的实例。
  5. 其他情况下则抛出错误。

下一节我将带领大家学习如何将XAML与过程式代码混合使用,在运行时加载和解析XAML

原文地址:https://www.cnblogs.com/yeanzhi/p/2932122.html