WPF学习(1) – XAML
2012-08-09 17:52 JustRun 阅读(1041) 评论(0) 编辑 收藏 举报1. 什么是XAML
定义
XAML是一种相对简单、通用的声明式编程语言,它适合于构建和初始化.NET对象.
XAML的表现形式是xml的格式,但是实际上它是一种编程语言,你能够用它来创建和初始化.Net对象。
和WPF的关系
XAML和WPF没有必然联系,它们是各自独立的。 任何其它.net技术都能够使用XAML, 比如(workflow).
所有XAML能够做的事情(构建和初始化.Net对象), 毫无疑问,都能够用C#等编程语言实现。
WPF中为什么使用XAML?
由于使用XAML来创建WPF显示层的对象,简单方便,所以实际上WPF的应用中都是和XAML一起使用的。
2. XAML如何构建和初始化.NET对象
要解决这些问题,需要解决:
- 如何引入.net命名空间, 这样XAML中才能识别这些类
- 如何创建类对象和为属性赋值
实际上, XAML规范定义了一些规则,用于把.NET命名空间、类型、属性和事件映射为XML命名空间、元素和特性
一个例子, XAML等价于下面的C#代码
XAML:
<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Content="OK"/>
C#:
System.Windows.Controls.Button b = new System.Windows.Controls.Button(); b.Content = "OK";
可以把上面的XAML代码保存成后缀为.xaml的文本文件,用IE打开,能看到一个按钮。
如何解决命名空间问题?
这段 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" , 做的是引入了.net framework的命名空间, 其中包含System.Windows.Controls.
xmlns理解为xml name space, 后面的网址,没有对应的网页,只是一个XAML定义的一个命名空间名称而已。一个xmlns可以对应多个.net framework中的多个命名空间。
实际上:
WPF把下面所有的.NET命名空间映射到XML命名空间http://schemas.microsoft.com/winfx/2006/xaml/presentation ,而这个命名空间将在整本书中使用。
System.Windows
System.Windows.Automation
System.Windows.Controls
System.Windows.Controls.Primitives
System.Windows.Data
System.Windows.Documents
System.Windows.Forms.Integration
System.Windows.Ink
System.Windows.Input
System.Windows.Media
System.Windows.Media.Animation
System.Windows.Media.Effects
System.Windows.Media.Imaging
System.Windows.Media.Media3D
System.Windows.Media.TextFormatting
System.Windows.Navigation
System.Windows.Shapes
如何解决类和属性问题?
XAML把.net中的类对应于标签, .net中的属性对应于标签属性。
3. 进一步了解XAML
属性元素
在XAML中,可以将属性作为元素使用,这样我们就可以方便的扩展。
C#:
System.Windows.Controls.Button b = new System.Windows.Controls.Button(); System.Windows.Shapes.Rentangle r = System.Windows.Shapes.Rentangle(); r.Width = 40; r.Height = 40; r.Fill = System.Window.Media.Brushes.Black; b.Content = r;
这段代码是在按钮上设置一个40*40的黑色矩形,使得按钮看起来像是一个播放器中的停止按钮。
它对应的XAML代码是:
<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <Button.Content> <Rectangle Height="40" Width="40" Fill="Black"/> </Button.Content> </Button>
上面的Rectangle还可以用属性元素,可以试试看。
类型转换器
上面的例子,有个疑问是, XAML中的字符串Black,是如何对应成System.Window.Meida.Brushes.Black的。 这里就是类型转换器的作用。
XAML解析器或编译器必须寻找一个类型转换器,该转换器知道如何将一个字符串表达式转换为一种想要的数据类型。WPF提供了许多常用数据类型的类型转换器,如Brush、Color、FontWeight、Point等,它们都是派生自TypeConverter的类(如BrushConverter、ColorConverter等),你也可以为自定义的数据类型写类型转换器。与XAML语言不同,类型转换器通常支持不区分大小写的字符串。
标记扩展
<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://chemas.microsoft.com/winfx/2006/xaml"> Background = "{x:Null}" Height="{x:Static SystemParameters.IconHeight}" Content="{Binding Path=Height, RelativeSource={RelativeSource Self}}" />
标记扩展,就像类型转换器一样,可以用于扩展XAML的表达能力。它们都可以在运行时计算字符串特性的值(除了一些内建的、为提高性能而在编译时计算的标记扩展),并生成一个合适的基于字符串的对象。就像类型转换器一样,WPF有好几个内建的标记扩展,你会发现它们都派生自本书最前面的内封中的MarkupExtension。
与类型转换器不同的是,标记扩展是通过XAML的显式的、一致的语法调用的,因此,标记扩展是最好的扩展XAML的方法。就是说类型转换都是在背地里做事情,而标记扩展很直观和好理解。
只要特性值由花括号({})括起来,XAML编译器或解析器就会把它认作一个标记扩展值而不是一个普通的字符串. 但并不是说标记扩展一定要{}括起来。
每个花括号中的第一个识别符是标记扩展类的名称
所以上面例子中, {x:Null}等就是标记扩展。x:Null, x:Static, Binding都是标记扩展的名称。
有些前面有x, 是因为它们属于这个命名空间 xmlns:x="httpschemas.microsoft.com/winfx/2006/xaml
没有x, 是因为它们属于默认命名空间 xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
4. 对象元素的子元素
一个对象元素可以有3中类型的子元素: 一个内容属性值,集合项, 或者一个能够通过类型转换到它的父元素的值。
内容属性值
大多数WPF类(通过定制特性)指定了一个属性,该属性可以被设置为XML元素中的任何内容。这个属性叫作内容属性。
像上面例子中的Button的Content就是内容属性, 可以设置成一个字符串,一个矩形等。
并不一定要把内容属性叫作Content,像ComboBox、ListBox和TabControl(也在System.Windows.Controls命名空间中)这样的类就使用Items属性作为内容属性。
集合项
List
List是实现了System.Collections.IList接口的集合.
比如下面的ListBox:
<ListBox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <ListBox.Items> <ListBoxItem Content="Item 1"/> <ListBoxItem Content="Item 2"/> </ListBox.Items> </ListBox>
Dictionary
Dictionary是实现了System.Collections.IDictionary接口的集合.
比如
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="httpschemas.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>
更多类型转换
比如
<SolidColorBrush>White</SolidColorBrush>
这与下面的代码等价:
<SolidColorBrush Color="White"/>
尽管Color没有被指定为内容属性。第一个XAML代码段能工作,是因为有类型转换器存在,会把字符串'white'转换成SolidColorBrush对象。
虽然类型转换器在实现XAML的可读性方面起了重大作用,但不足的是,它们让XAML变得更魔幻,从而更难理解XAML如何映射到.NET对象的实例。
5. XAML和代码混合使用
WPF允许任何一种.Net语言完全以过程式代码编写应用程序. 一些简单的应用程序可以完全写在XAML中.
尽管如此,大多数WPF应用程序是XAML与过程式代码的混合体
在运行时加载XAML
WPF的运行时XAML解析器公开为两个类,它们都位于System.Windows.Markup命名空间中:XamlReader和XamlWriter
A).XamlReader
XamlReader.Load方法的设置将解析XAML,创建合适的.NET对象,然后返回一个根元素的实例。
如果在当前目录下有一个XAML文件叫作MyWindow.xaml,它包含了一个Window对象作为根结点,那么可以使用下面的代码来加载和获得Window对象:
Window window = null; using(FileStream fs = new FileStream("MyWindow.xaml", FileMode.Open, FileAccess.Read) { //获取根元素,该元素是一个window对象 window = (Window)XamlReader.Load(fs); } StackPanel panel = (StackPanel)window.Content; Button okButtion = (Button)window.FindName("okButton"); //使用name来查找button.
B) 编译XAML
大多数WPF项目会通过MSBuild和Visual Studio完成XAML编译。XAML编译包括三项事情:将一个XAML文件转换为一种特殊的二进制格式,将转换好的内容作为二进制资源嵌入到正在被创建的程序集中,然后执行链接操作,将XAML和过程式代码自动连接起来。
但是如果要编译一个XAML文件并将它与过程式代码混合,第一步要做的就是为XAML文件的根元素指定一个子类,可以用XAML语言命名空间中的Class关键字来完成. (类似Asp.net中的CodeBehind)
![Creative Commons License](http://i.creativecommons.org/l/by/2.5/cn/88x31.png)
本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名justrun(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。