WPF笔记(1)XAML和code概述
WPF中的XAML(可扩展应用程序标记语言)是辅助的界面编程工具语言。它是基于XML的。每个XAML元素都是一个.NET CLR类。XAML主要用来进行对象的创建和初始化。 XAML经常来代替类的构造函数,用来布局和绑定事件。而事件的处理程序则一般在后台代码中实现。当然,有的也可以用数据绑定(data binding)来代替事件处理程序。这样,就可以把绑定放到XAML中了。
XAML使界面设计和逻辑代码分离开来。界面设计人员可以用XAML来关注关注于界面的设计。而程序人员则可以更关注于运行时的元素之间的交互。这种分离意味着,通常标记在一个文件中而代码则在另一个文件中。然而,这种分离仅在编译时存在。标记文件用于生成形成代码文件的代码,进而生成应用程序。
我们在XAML中看到的大部分类和属性都是WPF的一部分。但是,XAML并不是一个WPF规范的标记语言。WPF只是XAML的一种应用。XAML也可以被WPF以外的其它应用程序框架使用,(如:WWF)。
应用在WPF中的XAML所表示的元素都可以通过后台代码(code)来实现。
1、命名空间
XAML规范定义了一些元素和属性,你可以在WPF下的Xaml中使用它们。这些元素属于Xaml名字空间,而不是WPF空间,因此如果你要使用它们,则需要添加一个xaml的名字空间:http://schemas.microsoft.com/winfx/2006/xaml。
这是XAML语言命名空间,用于映射System.Windows.Markup命名空间中的类型,而且它也定义了XAML编译器或解析器中的一些特殊的指令。这些指令通常是作为XML元素的特性出现的,因此它们看上去像宿主元素的属性,但实际上并不是如此。
为了唯一性,名字空间经常用URL地址来表示。 xmlns用来表示名字空间。xmlns提供了一种方法把URI引用的名字空间定义为当前XML文件的元素和属性的默认名字空间。
对于XAML规范的元素和属性,我们通常添加一个声明前缀:x; 如:xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml。我们经常用的x:Class和x:Code就是属于XAML名字空间的。
表示WPF的名字空间的URL是http://schemas.microsoft.com/winfx/2006/xaml/presentation。
引用方法为:xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
隐式.NET命名空间
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
因为这是一个多对一的映射,WPF的设计者需要保证不要引入两个同样名称的类,虽然这些类是放在不同的.NET命名空间中的。
在WPF中,把http://schemas.microsoft.com/winfx/2006/xaml/presentatio作为默认(主要)命名空间,把http://schemas.microsoft.com/winfx/2006/xaml 作为次要命名空间,次要命名空间的前缀是x,这仅仅是一个规则,就像C#文件要以using System;指令开始一样。
自定义命名空间(利用clr-namespage)
名字空间的前缀我们可以使用任意的名字。例如在XAML文件中加入我们自己类。假设我们定义了一个MyNamespace名字空间的类MyControl。那么我们在需要用此控件的XAML文件中就可以引用该名字空间,前缀可以为stuff。如:
xmlns:stuff="clr-namespace:MyNamespace"
“clr-namespace:”必须是小写(就如同http:一样)。
这样我们在文件中就可以使用该控件属性。如:
<stuff:MyControl ... >
名字空间的前缀可以使用,但并不是必须的。如果代码中包含多个名字空间,那么就需要对每个名字空间使用前缀,此时前缀最好是名字空间的名字,以避免麻烦。如果所有的类都属于一个名字空间,则经常使用src作为名字前缀。如:
xmlns:src="clr-namespace:MyNamespace"
XAML除了可以引用本程序集的名字空间,也可以应用其它的程序集中的名字空间。此时只需要添加Assembly关键字属性即可。
如:xmlns:sys="clr-namespace:Windows;assembly=System"
上面表示此名字空间引用的时System程序集下的Windows命名空间。
2、属性元素
示例:
<Button xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”>
<Button.Content>
<Rectangle Height=”40” Width=”40” Fill=”Black”/>
</Button.Content>
</Button>
Button.Content中的句点可用于区分对象元素(object element)与属性元素(property element)。它们总是会以“类型名,属性名TypeName.PropertyName”的形式出现,总会包含在“类型名”对象元素中,但它们没有属于自己的特性。
3、类型转换器(TypeConverter)
示例:
<Button xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
Names= "button" Content=”OK”>
<Button.Background>
<SolidColorBrush Color=”White”/>
</Button.Background>
</Button>
XAML文件中的“White”是如何与C#中的System.Windows.Media.Brushes. White静态值White(类型为System.Windows.Media.SolidColorBrush)等价的呢?示例提供了一些如何使用字符串设置在XAML属性的细节,这些属性的类型既不是System.String,也不是System.Object。在这样的情况下,XAML解析器或编译器必须寻找一个类型转换器,该转换器知道如何将一个字符串表达式转换为一种想要的数据类型。WPF提供了许多常用数据类型的类型转换器,如Brush、Color、FontWeight、Point等,它们都是派生自TypeConverter的类(如BrushConverter、ColorConverter等),你也可以为自定义的数据类型写类型转换器。与XAML语言不同,类型转换器通常支持不区分大小写的字符串。
转换器列表,可参考:ms-help://MS.MSDNQTR.v90.chs/fxref_system/html/35bffd5f-b9aa-1ccd-99fe-b0833551e562.htm
上述代码的实际转换行为:
var typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(Brush));
this.button.BackGround= (Brush)typeConverter.ConvertFromInvariantString("White");
4、标记扩展(MarkExtension)
标记扩展,就像类型转换器一样,可以用于扩展XAML的表达能力。它们都可以在运行时计算字符串特性的值(除了一些内建的、为提高性能而在编译时计算的标记扩展),并生成一个合适的基于字符串的对象。就像类型转换器一样,WPF有好几个内建的标记扩展,它们都派生自MarkupExtension。
但与类型转换器不同的是,标记扩展是通过XAML的显式的、一致的语法调用的,因此,标记扩展是最好的扩展XAML的方法。
只要特性值由花括号({})括起来,XAML编译器或解析器就会把它认作一个标记扩展值而不是一个普通的字符串
(或其他一些需要进行类型转换的东西)。
5、子元素
一个对象元素可以有3种类型的子元素:一个内容属性值,集合项,或者一个能够通过类型转换到它的父元素的值。
Content
大多数WPF类(通过定制特性)指定了一个属性,该属性可以被设置为XML元素中的任何内容。这个属性叫作内容属性,它确实是一个让XAML呈现变得更轻便简单的捷径。
集合项(Collections)
XAML允许将项添加到支持索引的两种类型的集合中:List和Dictionary。
List是实现了System.Collections.IList接口的集合,如System.Collections.ArrayList和许多WPF定义的集合类都是List。
System.Windows.ResourceDictionary是WPF中的一个常用的集合类型。它实现了System.Collections.IDictionary接口,因此能够支持在过程式代码中添加、移除和枚举键/值对,这与创建一个典型的散列表是一样的。
其它
为了避免混淆,当转换子元素时,任何一个有效的XAML解析器或者编译器必须遵循下面的规则:
(1) 如果该类型实现了IList接口,就为每个子元素调用IList.Add。
(2) 否则,如果该类型实现了IDictionary,就为每个子元素调用IDictionary.Add,在该值的键和元素中使用x:Key特性值。
(3) 否则,如果父元素支持内容属性(由System.Windows.Markup.ContentPropertyAttri- bute表示),而且子元素的类型与该内容属性是兼容的,就把子元素作为它的值。
(4) 否则,如果子对象是普通文本,且有类型转换器将子对象转换为父类型(没有在父元素上设置属性),则把子元素作为类型转换器的输入,将输出作为父对象的实例。
(5) 其他情况下,则抛出一个错误。
6、XamlReader和XamlWriter
WPF允许用任何一种.NET语言完全以过程式代码编写应用程序。另外,一些简单的应用程序可以完全写在XAML中,尽管如此,大多数WPF应用程序是XAML与过程式代码的混合体。
WPF的运行时XAML解析器公开为两个类,它们都位于System.Windows.Markup命名空间中:XamlReader和XamlWriter,而且它们的API已经再简单不过了。XamlReader包含了一些对静态Load方法的重载,而XamlWriter包含了一些对静态Save方法的重载。因此,用任何一种.NET语言写的程序都可以在运行时依赖XAML。