WPF入门之XAML初窥

1. 什么是XAML?

XAML是一种相对简单、通用的声明式变成语言,它适合于构建和初始化.NET对象。它由一些规则和关键字构成,但是它自己没有任何有意义的元素。在没有WPF/WF框架的基础上讨论XAML就象在没有.NET Framework的基础上讨论C#一样是没有任何意义的,因为它本身并不能提供任何有意义的元素,需要由WPF/WF框架或者说.NET XAML编译器和WPF应用框架来承载、理解XAML的表达意义。由于XAML的通用性,实际上你可以把它应用于任何.NET技术。然而,是否在使用WPF时使用XAML是可选的,每一个XAML能做的事情完全可以由任何一种你喜欢的.NET语言来实现,但是反过来是不行的。在后边的解释中你会看到,实际上针对XAML的解释,XAML编译器是把XAML语句与.NET对象/类型联系在一起的,将XAML纳入和.NET类型相同的模型中控制是他们为什么能够互相兼容的重要原因。

例如如下的XAML片段和.NET C#语句所表达的结果是相同的:

XAML: <Button xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation Content="OK" />

C#:     System.Windows.Controls.Button btnOk = new System.Windows.Controls.Button();

          b.Content = "OK";

2. XAML元素及特性

2.1 XAML命名空间

XAML文件的跟对象元素必须至少有一个XML命名空间,用于验证自己和其子元素。你可以在根元素或子元素上声明额外的XML命名空间来标识你的自定义元素,但每个命名空间下的标识符都必须有一个唯一的前缀。我们把http://schemas.microsoft.com/winfx/2006/xaml/presentation作为默认(主要)的命名空间,我们在使用大多数控件时都使用此主命名空间,因为WPF通过硬编码的方式将此命名空间与.NET的命名空间进行了映射。而对于次命名空间,我们通常需要添加前缀来表示其命名空间在以下范围内被引用,中就像C#中的using System;一样,声明了一个可以引用的命名空间。以下代码片段演示了如何使用主命名空间和次命名空间:

<UserControl x:Class="MediaPlayer.Page"
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="450" Height="300">
    <Grid x:Name="LayoutRoot" Background="White">
        <TextBlock FontSize="12" FontWeight="Bold" HorizontalAlignment="Center">Vedio Player</TextBlock>
    </Grid>
</UserControl>

2.2 属性元素(Property Element)

属性元素本质上是为了增加在元素中包含子元素的一种方式。它是XAML提供的用来替代更加详细的语法来设置属性值的方法。例如:

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >

    <Button.Content>

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

    </Button.Content>

</Button>

Content属性现在被设置为一个XML元素而不是XML属性,Button.Content中的句点用来区分对象元素与属性元素。属性元素总会以“类型名.属性名”的形式出现并包含在“类型名”对象元素中。说白了,属性元素是为了扩展某类型的属性而存在的。

2.3 类型转换器(Type Converter)

在XAML中实际上我们都是以String的类型来赋予各种属性值的,但在对于.NET这样的有类型库来讲,不是所有的属性值都是为String的,比如对于Button的Background属性,在C#中我们需要这样来写:

System.Windows.Controls.Button b = new System.Windows.Controls.Button();

b.Content = “OK”;

b.Background = System.Windows.Media.Brushes.White;

这段C#代码等同于下边的XAML代码片段:

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Content="OK">

   <Button.Background>

White

</Button.Background>

</Button>

可以很容易的发现,在C#中Button的Background属性对应的类型为System.Windows.Media.Brushes,而在XAML中由于无法具有强类型表现方式(当然它是通过另一种替代方式来表现的,只是表面上都是String)这里选择了用White这个字符串来表示我们想用White颜色来作为背景颜色。因为这个代码片段是等同的,我们可以自然的将White字符串认为等同于System.Windows.Media.Brushes.White。而这个映射就是通过类型转换器来实现的。这里就通过BrushConverter和ColorConverter一起将White设置为Button的Background(因为Background实际上是Brush类型的)-而这些转换器都是派生自TypeConverter的类。PS:这里另一个参考就是我们在写ASP.NET的自定义控件时里边都会有定义一些Converter,但他们是不一样的。

其实以上的XAML代码是简化的写法,更好的理解它我们可以写为下边这种方式(等价的):

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Content="OK">

   <Button.Background>

<SolidColorBrush Color=”White” />

</Button.Background>

</Button>

而对应的C#代码,为了更好的理解类型转换器,我们改写为下边这种方式:

System.Windows.Controls.Button b = new System.Windows.Controls.Button();

b.Content = “OK”;

b.Background = (Brush)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Brush)).ConvertFromInvariantString(“White”);

2.4 扩展标记

扩展标记就像类型转换器一样是用来扩展XAML的表达能力的,他们都可以在运行时计算字符串特性的值并生成合适的基于字符串的对象。但与类型转换器不同的是,标记扩展是通过XAML的显式的、一致的语法调用的,因此这是比较好的扩展XAML的方法。一般来讲我们更多的把扩展标记应用于Resource, Binding等。如下边的例子我们通常会用来标记当前元素/对象是使用的样式(Resource):

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

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

Title="Simple Window">

<Window.Resources>

<SolidColorBrush x:Key="backgroundBrush">Yellow</SolidColorBrush>

<SolidColorBrush x:Key="borderBrush">Red</SolidColorBrush>

</Window.Resources>

<DockPanel>

<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"

HorizontalAlignment="Center">

<Button Background="{StaticResource backgroundBrush}"

BorderBrush="{StaticResource borderBrush}" Margin="5">

<Image Height="21" Source="zoom.gif"/>

</Button>

</StackPanel>

</DockPanel>

</Window >

2.5 集合项

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

List: 实现了System.Collections.IList接口的集合,它的Items属性是实现了IList的ItemCollection类型;

Dictionary: 实现了System.Collections.IDictionary接口的集合,能够支持在过程式代码中添加、移除和枚举键/值对。

下边两个例子展示了在XAML中如何应用集合项。注意:由于Content属性实际上相当于在.NET对象中的默认属性(例如在自定义控件中的默认属性),所以可以将内容属性的值作为此对象的直接子元素而不用Content属性元素来标明,以此来简化XAML的复杂度。

<ListBox xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation>

<ListBox.Items> <!—直接将子元素作为内容属性—>

<ListBoxItem Content=”Item 1” /><!—等同于<ListBoxItem>Item 1</ListBoxItem>-->

<ListBoxItem Content=”Item 2” />

</ListBox.Items>

</ListBox>

3. 编译XAML

XAML编译 通常包括三项事情:将一个XAML文件转换为一种特殊的二进制格式(BAML:Binary Application Markup Language);将转换好的二进制资源嵌入到正在被创建的程序集中;然后执行链接操作将XAML和过程式代码自动连接起来。

每个XAML都会在编译过程中产生过程式代码,这是在编译过程中动态生成的,但这些过程代码仅仅是“粘合代码”Glue Code,类似于在运行时加载和解析松散XAML文件时所需要的代码(和普通的Win Form自动生成的代码用途类似),你可以在.g.cs(.g.vb)文件中找到这些代码。

同样你可以在XAML中混合使用过程代码(Code inside),当XAML编译后X:code元素中的部分将会放到部分类.g.cs文件中。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

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

<Button Click=”button_Click”>OK</Button>

<x:Code><![CDATA[

Void button_Click(object sender, RouteEventArgs e)

{

this.Close();

}

]]></x:Code>

</Window>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值