什么是 XAML?
XAML 是一种声明性标记语言。如同应用于 .NET Framework 编程模型一样,XAML 简化了为 .NET Framework 应用程序创建 UI 的过程。您可以在声明性 XAML 标记中创建可见的 UI 元素,然后使用代码隐藏文件(通过分部类定义与标记相连接)将 UI 定义与运行时逻辑相分离。XAML 直接以程序集中定义的一组特定后备类型表示对象的实例化。
下面的示例演示如何创建作为 UI 一部分的按钮。此示例的目的仅在于供您初步了解 XAML 是如何表示常用 UI 编程形式的(它不是一个完整的示例)。
XAML 语法概述
XAML 对象元素
此示例指定了两个对象元素:(含有内容,后面有一个结束标记)和 (自结束形式,包含几个特性)。对象元素 StackPanel 和 Button 各映射到一个类名,这些类由 WPF 定义并且是 WPF 程序集的一部分。指定对象元素标记时会创建一条 XAML 处理指令来创建一个新实例。每个实例都是在分析和加载 XAML 时通过调用基础类型的默认构造函数来创建的。
特性语法(属性)
对象的属性通常可表示为对象元素的特性。特性语法命名在特性语法中设置的属性,后跟赋值运算符 (=)。特性的值始终以包含在引号中的字符串的形式进行指定。
特性语法是最简单有效的属性设置语法,并且对于曾使用过标记语言的开发人员而言在使用中是最直观的语法。例如,以下标记将创建一个具有红色文本和蓝色背景的按钮,还将创建指定为 Content 的显示文本。
属性元素语法
对于对象元素的某些属性,特性语法是不可能实现的,因为无法在特性语法的引号和字符串限制内充分地表达提供属性值所必需的对象或信息。对于这些情况,可以使用另一个语法,即属性元素语法。
属性元素开始标记的语法为 。通常,该标记的内容是类型的一个对象元素,属性会将该元素作为其值。指定内容之后,必须用一个结束标记结束属性元素。结束标记的语法为 。
如果可以使用特性语法,那么使用特性语法通常更为方便,且能够实现更为精简的标记,但这通常只是一个风格的问题,而不属于技术限制。下面的示例演示了在前面的特性语法示例中设置的相同属性,但这次对 Button 的所有属性使用了属性元素语法。
This is a button
集合语法
XAML 语言包含一些优化,可以生成可读性更好的标记。其中的一项优化是:如果某个特定属性采用集合类型,则您在标记中声明为该属性的值内的子元素的项将成为集合的一部分。在这种情况下,子对象元素的集合是设置为集合属性的值。
下面的示例演示为 GradientStops 属性设置值的集合语法:
XAML 内容属性
XAML 指定了一个语言功能,通过该功能,一个类可以指定它的一个且仅一个属性为 XAML 内容属性。该对象元素的子元素用于设置该内容属性的值。换言之,仅对内容属性而言,您可以在 XAML 标记中设置该属性时省略属性元素,并在标记中生成更直观的父级/子级形式。
例如,Border 指定内容属性 Child。系统处理下面两个 Border 元素的方式相同。第一个元素利用了内容属性语法而省略了 Border.Child 属性元素。第二个元素显式标明 Border.Child。
作为 XAML 语言的规则,XAML 内容属性的值必须完全在该对象元素的其他任何属性元素之前或之后指定。例如,下面的标记无法进行编译:
复制
I am a
Blue
blue button
有关 XAML 内容属性的此项限制的更多信息,请参见 XAML 语法详述的“XAML 内容属性”一节。
文本内容
有少量 XAML 元素可直接将文本作为其内容来处理。若要实现此功能,必须满足以下条件之一:
- 类必须声明一个内容属性,并且该内容属性必须是可赋值给字符串的类型(该类型可以是 Object)。例如,任何 ContentControl 都将 Content 用作其内容属性,并且其类型为 Object,这样就支持实际的 ContentControl(例如,Button)上的如下用法:Hello。
- 类型必须声明一个类型转换器,该类型转换器将文本内容用作其初始化文本。例如,Blue。这种情况实际上并不常见。
- 类型必须为已知的 XAML 语言基元。
内容属性和集合语法组合
请看以下示例:
First Button
Second Button
此例中,每个 Button 都是 StackPanel 的一个子元素。这是一个简单直观的标记,其中出于两个不同的原因省略了两个标记。
- 省略的 StackPanel.Children 属性元素:StackPanel 从 Panel 派生。Panel 将 Panel.Children 定义为其 XAML 内容属性。
- 省略的 UIElementCollection 对象元素:Panel.Children 属性采用类型 UIElementCollection,该类型实现 IList。根据处理集合(例如 IList)的 XAML 规则,集合的元素标记可以省略。(在这种情况下,UIElementCollection 实际无法实例化,因为它没有公开默认构造函数,这就是 UIElementCollection 对象元素以注释形式出现的原因。)
First Button
Second Button
特性语法(事件)
特性语法还可用于事件成员,而不仅限于属性成员。在这种情况下,特性的名称为事件的名称。在 XAML 事件的 WPF 实现中,特性的值是实现该事件的委托的处理程序的名称。例如,以下标记将 Click 事件的一个处理程序指定给在标记中创建的 Button:
Click Me!
XAML 中的大小写和空白
XAML 通常区分大小写。出于解析后备类型的目的,WPF XAML 按照 CLR 区分大小写的相同规则区分大小写。按名称与程序集中的基础类型进行比较或者与类型的成员进行比较时,对象元素、属性元素和特性名称均必须使用区分大小写的形式指定。XAML 语言关键字和基元也区分大小写。值并不总是区分大小写。值是否区分大小写将取决于与采用该值的属性关联的类型转换器行为,或取决于属性值类型。例如,采用 Boolean 类型的属性可以采用 true 或 True 作为等效值,但只是因为将字符串转换为 Boolean 的本机 WPF XAML 分析器类型转换已经允许将这些值作为等效值。
WPF XAML 处理器和序列化程序将忽略或删除所有无意义的空白,并规范化任何有意义的空白。这与 XAML 规范的默认空白行为建议一致。通常,只有当您在 XAML 内容属性中指定字符串时,此行为的重要性才会体现出来。简言之,XAML 将空格、换行符和制表符转化为空格,如果它们出现在一个连续字符串的任一端,则保留一个空格。有关 XAML 空白处理的完整说明不属于本主题的讨论范围。
标记扩展
标记扩展是一个 XAML 语言概念。当用于提供特性语法的值时,大括号({ 和 })表示标记扩展用法。此用法指示 XAML 处理系统不要像通常那样将特性值视为一个文本字符串或者可转换为字符串的值。
WPF 应用程序编程中最常用的标记扩展是 Binding(用于数据绑定表达式)以及资源引用 StaticResource 和 DynamicResource。通过使用标记扩展,即使属性通常不支持特性语法,也可以使用特性语法为属性提供值。标记扩展经常使用中间表达式类型实现一些功能,例如,推迟值或引用仅在运行时才存在的其他对象。
例如,下面的标记使用特性语法设置 Style 属性的值。Style 属性采用了 Style 类的一个实例,该实例默认情况下未能用特性语法字符串实例化。但在本例中,特性引用了特定的标记扩展 StaticResource。当处理该标记扩展时,它返回对以前在资源字典中作为键控资源进行实例化的某个样式的引用。
...
...
有关特定在 WPF 中实现的所有 XAML 标记扩展的参考列表,请参见 WPF XAML 扩展。有关由 System.Xaml 定义并且可更广泛用于 .NET XAML 实现的标记扩展的参考列表,请参见 XAML 命名空间 (x:) 语言功能。有关标记扩展概念的更多信息,请参见标记扩展和 WPF XAML。
类型转换器
在一节中,曾提到特性值必须能够使用字符串进行设置。对字符串如何转换为其他对象类型或基元值的基本本机处理取决于 String 类型本身,以及对某些类型(如 DateTime 或 Uri)的本机处理。但是很多 WPF 类型或这些类型的成员扩展了基本字符串特性处理行为,因此可以指定更复杂的对象类型的实例作为字符串和特性。
Thickness 结构是一个类型示例,该类型拥有可使用 XAML 的类型转换。Thickness 指示嵌套矩形中的度量并用作一些属性(如 Margin)的值。通过对 Thickness 设置类型转换器,所有使用 Thickness 的属性都可以更容易地在 XAML 中指定,因为它们可指定为特性。下面的示例使用类型转换和特性语法来为 Margin 提供值:
上面的特性语法示例与下面更为详细的语法示例等效,但在下面的示例中,Margin 改为通过包含 Thickness 对象元素的属性元素语法进行设置。而且设置 Thickness 的四个关键属性作为新实例的特性:
说明
| 还有少数对象只能通过类型转换这种公开方式在不涉及到子类的情况下为该类型设置属性,因为类型本身并没有默认构造函数。一个示例是 Cursor。
|
有关如何支持类型转换及其在特性语法上的应用的更多信息,请参见 TypeConverters 和 XAML。
XAML 根元素和 XAML 命名空间
一个 XAML 文件只能有一个根元素,这样才能同时成为格式正确的 XML 文件和有效的 XAML 文件。对于典型的 WPF 方案,将使用在 WPF 应用程序模型中具有重要意义的根元素(例如,为页使用 Window 或 Page,为外部字典使用 ResourceDictionary 或为应用程序定义使用 Application)。下面的示例演示 WPF 页的典型 XAML 文件的根元素,此根元素为 Page。
|