可扩展应用程序标记语言 (XAML) 是一种声明性语言。您可以使用声明性 XAML 标记创建可见用户界面 (UI) 元素。然后可以使用单独的代码隐藏文件响应事件和操作使用 XAML 声明的对象。(个人理解:这里讲了后台代码与前台代码的分工)基于 XML 的声明性语言非常直观,可以为用户(尤其是具有 Web 设计和技术背景的人员)创建从原型到生产的各种界面。
XAML 文件是通常具有 .xaml 文件扩展名的 XML 文件。下面的示例演示非常基本的 Silverlight XAML 文件的内容。
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
XAML 区分大小写
XAML 是一种区分大小写的语言。这是 XAML 基于 XML 的另一种体现,因为根据 XML 语言定义,XML 是区分大小写的。XAML 元素和属性的名称区分大小写。属性 (Attribute) 值可能区分大小写,这取决于如何针对特定属性 (Property) 处理属性 (Attribute) 值。例如,如果属性值声明了枚举成员名称,则对成员名称字符串进行类型转换以返回枚举成员值的内置行为不区分大小写。与之相反,Name 属性的值,以及用于根据 Name 属性声明的名称处理对象的实用工具方法,将名称字符串视为区分大小写。
声明对象
可通过以下两种方法用 XAML 声明对象:
∙直接使用对象元素语法:使用开始标记和结束标记将对象声明为 XML 元素。可以使用此语法声明根对象或设置属性值。
∙间接使用属性语法:使用内联值声明对象。可以使用此语法设置属 性值。这是一个针对 XAML 处理器的间接操作,因为必须有一些后台内容知道如何在了解正设置何种属性和提供的字符串值的基础上创建新对象。通常,这表明相关类型或属性支持可处理字符 串输入的类型转换器。
这并不意味着始终 可以选择使用对象元素语法或属性语法。某些对象只能使用对象元素语法创建。少量对象只能通过初始设置为属性值来创建。在 Silverlight 中,可使用对象元素或属性语法创建的对象比较少。
除了声明对 象,XAML 中还提供了一些可以用来引用现有对象的方法。本主题的标 记扩展一节中将进行详细讨论。
使用对象元素语法声明对象
若要使用对象元素语法声明对 象,需要编写以下两个元素标记,其中 objectName 是要实例化的对象的名称。在本文档中,经常出现术语"对象元素",这是用于用对象元素语法创建 XAML 对象的特定标记的简称。
下 面的示例使用对象元素语法声明 Canvas 对象。
某些对象(例如 Canvas) 可以包含其他对象。
为方便起见(且作为 XAML 与 XML 的一般关系的一部分),如果对象不包含其他对象,则可以使用一个自结束标记(而不是开始/结束标记对)来声明对象元素,如下面示例中的
使用属性语法声明对象
在某些情况下,属性 (Property) 值并不只是语言基元(如字符串),此时可以使用属性 (Attribute) 语法来实例化设置该属性 (Property) 的对象类型,并设置定义新对象的键属性 (Property)。由于此行为绑定到属性 (Property) 设置,请参见以下各节了解有关如何使用属性 (Attribute) 语法在一个步骤中声明对象并设置其属性 (Property) 的信息。
设置属性
可以设置使用对象元素语法声明的对象的属性。可以通过多种方法使用 XAML 设置属性:
∙使用属性语法。
∙使 用属性元素语法。
∙使用内容元素语法。
∙使用集合语法(通常是隐式集合语法)。
对于对象声明,此方法列表并不表示可以使用这些方法中的任何一种来设置给 定的属性。某些属性只支持其中一种方法。某些属性 (Property) 可能支持组合;例如,支持内容元素语法的属性 (Property) 可能还支持属性 (Property) 元素语法或属性 (Attribute) 语法。这取决于属性和属性使用的对象类型。可用 XAML 设置的每个属性的参考页的"XAML 用法"部分指出了使用 XAML 语法的可能性。还有一些无论使用任何方式都无法使用 XAML 设置的 Silverlight 属性,必须使用代码来设置这些属性。
无 论使用任何方式(包括 XAML 或代码)都无法设置只读属性,除非有其他机制适用。该机制可能是调用一个设置为属性的内部表示形式的构造函数重载、一个并非是严格意义上的属性访问器的方 法、一个属性关系(例如一个依赖于其他可设置属性的值的计算属性,以及服务或行为对该属性值的可能影响)。另外,集合给出了一种您正在设置只读属性的假 象,实际上您设置的不是只读属性(请参见使 用集合语法设置属性)。
使用属性 (Attribute) 语法设置属性 (Property)
使用以下语法,其中 objectName 是要实例化的对象,propertyName 是要对该对象设置的属性的名称,propertyValue 是要设置的值。
-or-
...
使 用上述任何一种语法都可以声明对象并设置该对象的属性。虽然第一个示例是标记中的单一元素,实际上这里有一些与 XAML 处理器如何分析此标记有关的分离步骤。首先,对象元素的存在表明必须实例化新的 objectName 对象。只有存在这样的实例后,才可以对它设置实例属性 propertyName。
下 面的示例使用三个属性 (Attribute) 的属性 (Attribute) 语法来设置 Rectangle 对象的 Width、Height 和 Fill 属性 (Property)。
使用属性元素语法设置属性
某些属性可以使用属性元素语 法来设置。若要使用属性元素语法,必须能够指定对象元素的新实例才能"填充"属性元素值。
若要使用属性元素语法,需要为要设置的属性创建 XML 元素。这些元素的形式为 在下面的语法中,property 是要设置的属性的名称,propertyValueAsObjectElement 是声明新对象的新对象元素,其值类型是该属性期望的值。 下面的示例使用属性元素语法通过 SolidColorBrush 对象元素来设置 Rectangle 的填充。(在 SolidColorBrush 中,Color 使用属性语法来设置。)此 XAML 的呈现结果等同于前面使用属性语法设置 Fill 的 XAML 示例。 Height="100" > 使用内容元素语法设置属性 某些 Silverlight 对象定义一个属性,该属性允许您使用的 XAML 语法忽略该属性的名称,以及通过提供所属类型的对象元素标记中的一个值来设置该属性。这称为内容元素语法。如果内容元素语法可用,Silverlight 参考文档中属性语法的"XAML 用法"部分将显示该语法。例如,TextBlock 的 Text 属性 (Property) 页显示了另一种 XAML 语法,该语法使用内容元素语法(而不是属性 (Attribute) 语法)来设置 Text 的字符串值。 下面的示例在未显式指定 Text 属性的情况下设置 TextBlock 的 Text 属性。在此例中,属性 (Property) 是使用 XML 视为内容或"内部文本"的信息设置的,而不是通过使用属性 (Attribute) 或声明对象元素来设置。 Hello! XAML 中的集合具有很多集合语法的变体,很有意义。另外,XAML 看上去似乎允许您"设置"只读集合属性。而实际上,XAML 允许的操作是向集合中添加项。 XAML 集合语法中始终忽略的是保留集合项的集合类型的属性。在许多情况下,这样的属性被定义为 CLR 索引器。对于集合而言,XAML 中的集合实际所需的不是属性,而是方法:Add 方法。因此,当 XAML 处理器遇到集合语法中的一个或多个对象元素时,首先创建每个此类对象,然后通过调用集合的 Add 方法将每个新对象添加到集合中。 下面的示例演示了一个使用可构造集合类 型的集合属性(可以定义实际的集合并将其实例化为 XAML 中的一个对象元素)。 不过通常而言,对于采用集合的 Silverlight 属性,XAML 分析器可根据集合所属的属性隐式知道集合的类型。因此,可以省略集合本身的对象元素,如下面的示例所示。 另外,有一些属性不但是集合属性还标识为类的内容属性。前面示例中使用的 GradientStops 属性就是这种情况。因此,也可以省略属性元素。这生成以下标记: 在广泛用于控件合成的类(例如面板)中,此集合和内容语法的组合是最常见的。例如, 下面的示例演示将两个 UI 元素合成到一个 StackPanel 中的显式 XAML 以及可能的最简单 XAML。 请注意显式语法中注释掉的 UIElementCollection。 将其注释掉是因为 UIElementCollection 不是可构造的类,即使相关集合将在创建的对象树中存在,也不能在 XAML 中显式指定它。在某些情况下,标记中会特意且显式包含集合类(例如赋予集合一个 x:Name, 以便可以在代码中更方便地引用该集合)。但是,注意不要显式声明由于其类特征而无法由 XAML 分析器构造的集合类。 何时使用属性 (Attribute) 语法或属性 (Property) 元素语法来设置属性 (property) 所有支持使用 XAML 设置的属性 (Property) 都支持用于直接值设置的属性 (Attribute) 语法或属性 (Property) 元素语法,但可能不会互换支持每种语法。某些属性支持上述两种语法,某些属性还支持其他语法选项(例如前面所示的 Text 的内容元素语法)。属性支持的 XAML 语法的类型在某种程度上取决于该属性用作其属性类型的对象的类型。如果该属性 (Property) 类型为基元类型(例如双精度、整型或字符串),则该属性 (Property) 始终支持属性 (Attribute) 语法。 下面的示例 使用属性语法设置 Rectangle 的宽度。Width 属性 (Property) 支持属性 (Attribute) 语法,这是因为属性 (Property) 值是双精度值。 如果可以通过对字符串进行类型转换来创建用于设置某属性 (Property) 的对象类型,也可以使用属性 (Attribute) 语法来设置该属性 (Property)。对于基元,始终是这种情况。但是,某些其他对象类型也可以使用指定为属性值的字符串(而不是需要对象元素语法)来创建。此方法使用 该特定属性或该属性类型通常所支持的基本类型转换。属性 (Attribute) 的字符串值经过分析后,字符串信息用于设置对新对象的初始化非常重要的属性 (Property)。特定类型转换器还可能创建公共属性类型的不同子类,这取决于它处理字符串中的信息的独特方式。支持此行为的对象类型将使用特殊语法 (在本文档的语法部分中列出)。 下面的示例使用属性语法设置 Rectangle 的填充。当使用 SolidColorBrush 设置 Fill 属性 (property) 时,该属性 (Property) 支持属性 (Attribute) 语法。这是因为支持 Fill 属性 (Property) 的 Brush 抽象类型支持类型转换语法,该语法可以创建一个通过将属性 (Attribute) 指定的字符串作为其 Color 来初始化的 SolidColorBrush(有 关此特定示例的详细信息,请参见 Brush 和 SolidColorBrush)。 如果用于设置某属性的对象支持对象元素语法,则可以使用属性元素语法来设置该属性。 如果该对象支持对象元素语法,该属性也支持属性元素语法。下面的示例使用属性元素语法设置 Rectangle 的填充。当使用 SolidColorBrush 设置 Fill 属性时,该属性支持属性元素语法,这是因为 SolidColorBrush 支持对象元素语法并满足该属性的使用 Brush 类型设置其值的要求。(SolidColorBrush 也使用属性 (Attribute) 语法设置了其 Color 属性 (Property)。此 XAML 的呈现结果等同于前面使用属性语法设置 Fill 的 XAML 示例。) 由于 Brush 类型转换器的原因,SolidColorBrush 成为唯一可针对新 Fill 值选择属性 (Property) 元素语法或属性 (Attribute) 语法(不使用资源引用或绑定)的 Brush 案例。对于可用于设置 Fill 的其他 Brush 类型,没有可用来创建该 Brush 类型的类型转换器行为。因此,如果要使用 brush 类型(例如 ImageBrush) 来设置 Fill, 必须对 Fill 使用属性元素语法并将 ImageBrush 声明为对象元素以提供属性值,或者使用下一节中介绍的标记扩展。 标记扩展 标记扩展是一个在 Silverlight XAML 实现中广泛使用的 XAML 语言概念。在 XAML 属性语法中,根据 XAML 规范,大括号({ 和 })表示标记扩展用法。此用法指示 XAML 处理不要像通常那样将属性值视为文本字符串或者视为可直接转换为文本字符串的值。相反,分析器通常应调用支持该特定标记扩展的代码,该标记扩展可帮助从标 记中构造对象树。 Silverlight 支持在其 XML 命名空间下定义且其 XAML 分析器可以理解的三种标记扩展。这些标记扩展是:Binding、StaticResource 和 TemplateBinding。 Binding 支持数据绑定。StaticResource 支持 ResourceDictionary 中定义的引用资源。TemplateBinding 支持 XAML 中可与模板化对象的代码属性交互的控件模板。Silverlight 还实现了一个在 XAML 命名空间中定义的标记扩展:x:Null。 采用引用类型值(类型没有转换器)的属性需要属性元素语法(该语法始终创 建新实例)或通过标记扩展的对象引用。Silverlight 标记扩展通常返回一个现有实例。通过使用标记扩展,每个可使用 XAML 设置的属性 (Property) 都可能可在属性 (Attribute) 语法中设置。即使属性 (Property) 不支持对直接对象实例化使用属性 (Attribute) 语法,也可以使用属性 (Attribute) 语法为属性 (Property) 提供引用值;或者可以使特定行为能够符合用值类型或实时创建的引用类型填充 XAML 属性 (Property) 这一常规要求。 例如,下面的示例使用属性 (Attribute) 语法设置 Border 的 Style 属性 (Property) 的值。Style 属性 (Property) 采用了 Style 类的实例,这是默认情况下无法使用属性 (Attribute) 语法字符串创建的引用类型。但在本例中,属性 (Attribute) 引用了特定的标记扩展 StaticResource。 当处理该标记扩展时,它返回对以前在资源字典中作为键控资源进行实例化的某个样式的引用。 ... ... 有关 标记扩展的参考列表,请参见 Silverlight 命名空间扩展或 XAML 命名空间 (x:) 语言功能。 文本"{"值 因为左大括号符号 { 是标记扩展序列的开始标记,所以,您必须使用转义符序列,以便指定以 { 开头的文本字符值。转义序列是 {}。例如,若要指定作为单个左大括号的字符值,请将属性值指定为 {}{。您还可以在某些情况下使用替代引号(例如,"" 分隔的属性值内的 '),以便将 { 值作为字符串提供。 事件 XAML 是用于对象及其属性的声明性语言,但它也可以包含用于将事件处理程序附加到标记中的对象的语法。可以将事件的名称指定为处理该事件的对象的属性名称。对于 属性值,可以指定在代码中定义的事件处理程序函数的名称。XAML 处理器使用此名称在加载的对象树中创建一个委托表示形式,并将指定的处理程序添加到内部处理程序列表中。 使用 XAML 时,所用的 API(托管或 JavaScript)会影响指定事件处理程序的方法。在 XAML 页级别上,这两种 API 是互相排斥的。使用哪个 API 取决于 XAML 页的根元素是否存在 x:Class 属性。如果存在 x:Class,则该页使用托管 API。如果不存在 x:Class,则该页使用 JavaScript API。 在托管 API 中,与当前 XAML 页关联的代码隐藏文件中必须存在事件处理程序,这是因为 XAML 和代码中的分部类必须联接起来才能添加该处理程序。有关详细信息,请参见代 码隐藏和分部类或Silverlight 的事件概述。 下面的 XAML 示例演示如何为 Canvas(在 本例中是 XAML 文件的根)的 Loaded 事件添加处理程序。此根中没有 x:Class,因而使用的是 JavaScript API。函数名称的解析因此推迟到运行时。在运行时,当发生该事件时,会针对名为"onLoaded" 的成员检查 JavaScript 脚本范围,并执行该函数。 名为 onLoaded 的函数是在 JavaScript 文件中定义的。该 JavaScript 文件通过 HTML 中 XAML、事件和代码隐藏 大多数基于 Silverlight 的应用程序都是由标记和代码隐藏源生成的。在一个项目中,XAML 被编写为 .xaml 文件,而使用 CLR 语言(如 Visual Basic 或 C#)编写代码隐藏文件。编译 XAML 文件时,通过将一个命名空间和类指定为 XAML 页的根元素的 x:Class 属性来确定每个 XAML 页的 XAML 代码隐藏文件的位置。 用于为对象元素添加行为的主要应用程序机制是使用该类的现有事件,并编写 在运行时引发该事件时调用的特定处理程序。通常在标记中指定事件名称以及要使用的处理程序的名称,而在代码隐藏中定义实现处理程序的代码。 XAML 根元素和 xmlns 一个 XAML 文件只能有一个根元素,这样才能成为格式正确的 XML 文件和有效的 XAML 文件。下面的示例演示 Silverlight"页"的典型 XAML 文件的根元素,根元素为 UserControl。 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > 根元 素还包含属性 xmlns 和 xmlns:x。这些属性向 XAML 处理器指明哪些 XML 命名空间包含标记引用的元素的元素定义。 前面示例中的 xmlns 属性具体指定了默认 XML 命名空间。在默认的 XML 命名空间中,可以不使用前缀指定标记中的对象元素。对于 Silverlight,默认 XML 命名空间几乎始终映射到 Silverlight 客户端命名空间 http://schemas.microsoft.com/winfx/2006/xaml/presentation。 前面示例中的 xmlns:x 属性指示另外一个 XML 命名空间,该命名空间映射 XAML 语言命名空间 http://schemas.microsoft.com/winfx/2006/xaml。 在具有此映射的文件的标记中引用时,XAML 命名空间定义的语言组件带有 x: 前缀。使用 xmlns 定义用法范围和映射的这种做法符合 XML 1.0 规范。请注意,只有在每个页面的根元素中以及应用程序定义中(如果标记中提供了应用程序定义),xmlns 属性才是必需的。xmlns 定义应用于根元素的所有子元素(此行为同样符合 xmlns 的 XML 1.0 规范)。还允许为根元素下的其他元素指定 xmlns 属性,并且这些属性将应用于定义元素的所有子元素。但是,在 Silverlight 中此用法并不常见,因为频繁定义或重新定义 XML 命名空间可能会导致 XAML 标记样式难以阅读。 x: 前缀 在前面的根元素示例中,前缀 x: 用于映射 XML 命名空间 http://schemas.microsoft.com/winfx/2006/xaml。 在此文档集的基于 Silverlight 的项目的模板、示例以及文档中,此 x: 前缀用于映射 XAML 命名空间。x: 前缀/XAML 命名空间包含多个将在 XAML 中非常频繁用到的编程构造。下面列出了将用到的最常见的 x: 前缀/XAML 命名空间编程构造: ∙x:Key: 为 ResourceDictionary 中的每个资源设置一个唯一键。 ∙x:Class: 指定为 XAML 页提供代码隐藏的类的 CLR 命名空间和类名称,并命名通过标记编译创建的类。必须具有这样一个类才能支持代码隐藏或支持初始化为 RootVisual, 也正是由于这些原因,即使没有资源,您也几乎总是会看到映射的 x:。 ∙x:Name: 处理 XAML 中定义的对象元素后,为运行时代码中存在的实例指定运行时对象名称。可以将 x:Name 用于不支持更方便的 FrameworkElement.Name 属性的非常见情形。 x: 前缀/XAML 命名空间中还有其他一些不太常见的编程构造。有关详细信息,请参见 XAML 命名空间 (x:) 语言功能。 资源字典 创建 ResourceDictionary 是一个常见任务,通常通过使用 XAML 创作所有资源字典来完成。有关更多信息,请参见资 源字典。 Silverlight XAML 中的结构定义 您通常可通过使用某一结构的 类型转换器启用的"mini-language"属性语法,声明作为结构的属性值。但是,为了将某一结构定义为资源,您必须将该结构定义为 ResourceDictionary 中的对象元素。这样做是必须的,因为您的结构需要 x:Key(如 果它在 ResourceDictionary 中存在)。Silverlight XAML 具有与某些结构有关的问题,以致您无法使用属性语法分配该结构的值。存在此问题的结构包括 CornerRadius、GridLength、Rect、Size、Thickness 和 Color。 为了为这些结构赋值,您使用称作初始化文本语法的对象元素语法的变体。该初始化文本语法由开始元素、该元素内作为内部文本的初始化文本以及结束元素构成。 您为初始化文本使用的字符串形式与为该结构启用的属性语法的类型转换器"mini-language"所使用的字符串形式相同。例如,下面的 XAML 为 Thickness 显示 ResourceDictionary 定义,该定义具有 x:Key 并且使用初始化文本为其可设置属性赋值: ... 下载本文
使用集合语法设置属性说明: 确 定哪些对象支持内容属性 (Property) 语法和哪些属性 (Property) 实现该语法的另一种方法是:检查应用于类型的 CLR 属性 (Attribute)。这可以通过反射来完成。支持内容元素语法的任何类型都将应用 ContentPropertyAttribute。
对于您自己的自定义程序集或 Silverlight 外的程序集,可以将该程序集指定为 XML 命名空间映射的一部分。通常,可以选择另一个前缀和非默认命名空间,但也可以选择另一个 XML 命名空间作为默认命名空间,然后将 Silverlight 映射到一个前缀。有关 XML 命名空间与程序集中后备代码的命名空间如何相关的更多信息,请参见 Silverlight XAML 命名空间以及将 XAML 命名空间映射为前缀。说明: 在 Silverlight 版本 1.0 时期,在 XAML 的模板中使用的默认 XAML 命名空间是 http://schemas.microsoft.com/client/2007。 该命名空间仍具有对旧版的支持,但强烈建议对任何当前的 Silverlight XAML 使用 http://schemas.microsoft.com/winfx/2006/xaml/presentation 作为默认命名空间 URI。这样做是出于迁移和工具原因:http://schemas.microsoft.com/winfx/2006/xaml/presentation 命名空间与 WPF 共享,并且某些工具可能不考虑 http://schemas.microsoft.com/client/2007 命名空间。