首页 > 代码库 > WPF学习------XAML 语法详述

WPF学习------XAML 语法详述

XAML 语言规范

XAML 语言规范中也定义或引用了此处定义的 XAML 语法术语。 XAML 是一种基于 XML 并遵循或扩展 XML 结构规则的语言。 其中某些术语共享自或基于描述 XML 语言或 XML 文档对象模型时常用的术语。

有关 XAML 语言规范的更多信息,请从 Microsoft 下载中心下载 [MS-XAML]。

XAML 和 CLR

XAML 是一种标记语言。 顾名思义,公共语言运行时 (CLR) 实现了运行时执行。 XAML 本身并非 CLR 运行时直接使用的一种公共语言。 而是可以将 XAML 视为支持其自身的类型系统。 WPF 所使用的特定 XAML 分析系统是根据 CLR 和 CLR 类型系统构建的。 在分析 WPF 的 XAML 时,XAML 类型将映射到 CLR 类型,以便将运行时表示形式实例化。 出于此原因,本文档中语法讨论的其余部分将包括对 CLR 类型系统的引用,而 XAML 语言规范中并未就这部分语法展开讨论。 (在 XAML 语言规范的每个级别,XAML 类型都可以映射到任何其他类型系统,而不一定要映射到 CLR,但这需要创建和使用一种不同的 XAML 分析器。)

ms788723.collapse_all(zh-cn,VS.110).gif类型成员和类继承

属性和事件在作为 WPF 类型的 XAML 成员时,通常从基类型继承而来。 请考虑此代码示例:<Button Background="Blue" .../> 如果要查看类定义、反射结果或文档,则Background 属性并不是 Button 类上立即声明的属性。 相反,Background 是从基 Control 类继承而来。

WPF XAML 元素的类继承行为与架构对 XML 标记的强制解释大相径庭。 类继承可能会变得很复杂,特别是在中间基类为抽象类或涉及到接口的情况下尤为如此。 由于这样一个原因,因此很难通过 XML 编程常用的架构类型(例如 DTD 或 XSD 格式)准确并完整地表示 XAML 元素及其所允许特性的集合。 另一个原因是,XAML 语言本身的扩展性和类型映射功能会对所允许类型和成员的任何固定表示形式的完整性造成妨碍。

对象元素语法

对象元素语法是一种 XAML 标记语法,它通过声明 XML 元素将 CLR 类或结构实例化。 这种语法类似于如 HTML 等其他标记语言的元素语法。 对象元素语法以左尖括号 (<) 开始,后面紧跟要实例化的类或结构的类型名称。 类型名称后面可以有零个或多个空格,对于对象元素还可以声明零个或多个特性,并用一个或多个空格来分隔每个“特性名="值"”对。 最后,必须存在下列一种情况:

  • 元素和标记必须用正斜杠 (/) 和紧跟的右尖括号 (>) 结尾。

  • 开始标记必须以右尖括号 (>) 结尾。 其他对象元素、属性元素或内部文本可以跟在开始标记后面。 此处可以包含的确切内容通常会受到元素对象模型的约束。 对象元素还必须存在等效的结束标记,并与其他开始标记/结束标记对形成正确的嵌套和平衡。

由 .NET 实现的 XAML 具有一组规则,可将对象元素映射为类型、将特性映射为属性或事件,以及将 XAML 命名空间映射到 CLR 命名空间和程序集。 对于 WPF 和 .NET Framework,XAML 对象元素映射到 Microsoft .NET 类型(如引用的程序集中所定义),而特性映射到这些类型的成员。 在 XAML 中引用 CLR 类型时,还可以访问该类型的继承成员。

例如,下面的示例是一个对象元素语法,该语法实例化 Button 类的一个新实例,而且还指定了一个 Name 特性及其值:

XAML
<Button Name="CheckoutButton"/>


下例是其中也包括 XAML 内容属性语法的对象元素语法。 其中包含的内部文本将用于设置 TextBox 的 XAML 内容属性 Text

XAML
<TextBox>This is a Text Box</TextBox>


ms788723.collapse_all(zh-cn,VS.110).gif内容模型

从语法上讲,类可能支持作为 XAML 对象元素的用途,但只有将该元素放置在整体内容模型或元素树中的应有位置时,该元素才能在应用程序或页面中发挥正常的作用。 例如,MenuItem 通常只应作为 MenuBase 派生类(如 Menu)的子级放置。 在可用作 XAML 元素的控件和其他 WPF 类的类页面上,将特定元素的内容模型记录为备注的一部分。

对象元素的属性

XAML 中的属性是由多种可能的语法设置的。 根据所设置属性的基础类型系统的特征,可用于特定属性的语法将有所不同。

通过设置属性值,可以在对象存在于运行时对象图中时为对象添加功能或特征。 从对象元素中创建的对象的初始状态基于默认的构造函数行为。 通常,您的应用程序将使用其他一些实例,而不是任何给定对象的完全默认的实例。

特性语法(属性)

特性语法是一种 XAML 标记语法,该语法声明现有对象元素中的特性,从而设置属性的值。 特性名称必须与支持相关对象元素的类的属性的 CLR 成员名称相匹配。 特性名称后面跟随一个赋值运算符 (=)。 特性值必须是用引号引起来的字符串。

说明 说明

可以使用替代引号在特性中放置文本引号。 例如,可以使用单引号作为声明其中包含双引号字符的字符串的一种方法。 无论使用单引号还是双引号,对于开始和结束特性值字符串都应该使用一对匹配的字符。 还有一些转义序列或其他技术可用于解决任何特定 XAML 语法规定的字符限制。 请参见 XML 字符实体和 XAML

为了通过特性语法进行设置,属性必须为公共属性,并且必须可写。 后备类型系统中属性的值必须为值类型,或者必须为可由 XAML 处理器在访问相关后备类型时实例化或引用的引用类型。

对于 WPF XAML 事件,作为特性名称被引用的事件必须是公共事件,并且必须具有公共委托。

属性或事件必须是由包含对象元素实例化的类或结构的成员。

ms788723.collapse_all(zh-cn,VS.110).gif特性值的处理

左右引号内包含的字符串值由 XAML 处理器进行处理。 对于属性,默认处理行为由基础 CLR 属性的类型确定。

特性值由下面的操作之一,按照如下处理顺序进行填充:

  1. 如果 XAML 处理器遇到大括号或从 MarkupExtension 派生的对象元素,则首先计算引用的标记扩展(而不是将值作为字符串进行处理),然后使用该标记扩展返回的对象作为值。 在许多情况下,标记扩展返回的对象是对现有对象的引用或是将计算推迟到运行时的表达式,而不是新实例化的对象。

  2. 如果属性是用特性化 TypeConverter 声明的,或者该属性的值类型是用特性化 TypeConverter 声明的,则该特性的字符串值将作为转换输入提交到类型转换器,然后转换器将返回新的对象实例。

  3. 如果没有 TypeConverter,则将尝试直接转换为属性类型。 此最终级别是在 XAML 语言基元类型之间直接转换本身具有分析器的值、或检查枚举(分析器随后将访问匹配的值)中命名常量的名称。

ms788723.collapse_all(zh-cn,VS.110).gif枚举特性值

XAML 中的枚举由 XAML 分析器进行内部处理,而枚举的成员则应该通过指定枚举的某个命名常量的字符串名称进行指定。

对于无标志的枚举值,本机行为是处理特性值的字符串并将它解析为某个枚举值。 您不必像在代码中那样指定格式为枚举. 的枚举, 而是仅指定枚举 将从所设置属性的类型推断。 如果您指定格式为枚举. 的特性,它将无法正确解析。

对于按标志枚举,该行为基于 Enum.Parse 方法。 您可以通过用逗号分隔每个值来为按标志枚举指定多个值。 但是,您不能合并不按标志的枚举值。 例如,不能尝试使用逗号语法来创建作用于无标志枚举多个条件的 Trigger

<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value=http://www.mamicode.com/"Collapsed,Hidden">>

在 WPF 中,很少有按标志枚举能支持可在 XAML 中设置的特性。 但是,StyleSimulations 就是这样的一个枚举。 例如,可以使用逗号分隔的按标志特性语法修改在 Glyphs类的“Remarks”(备注)部分中提供的示例;StyleSimulations = "BoldSimulation" 可以变为 StyleSimulations = "BoldSimulation,ItalicSimulation" KeyBinding.Modifiers是另一个其中可指定多个枚举值的属性。 但是,此属性恰好是一个特例,因为 ModifierKeys 枚举支持其自身的类型转换器。 修饰符的类型转换器使用加号 (+) 而不是逗号 (,) 作为分隔符。 此转换支持用更传统的语法表示 Microsoft Windows 编程中的组合键(如“Ctrl+Alt”)。

ms788723.collapse_all(zh-cn,VS.110).gif属性引用和事件成员名称引用

指定特性时,可以引用作为您为包含对象元素实例化的 CLR 类型的成员而存在的任何属性或事件。

或者,可以独立于包含对象元素来引用附加属性或附加事件。 (后面的某节即将讨论附加属性。)

对于可通过默认命名空间访问的任何对象中的任何事件,还可以通过使用“类型名称.事件”部分限定名来命名;此语法支持为路由事件附加处理程序,在路由事件中,处理程序旨在处理子元素中的事件路由,但是父元素在其成员表中并不拥有该事件。 此语法与附加事件语法相似,但此处的事件不是真正的附加事件。 相反,您引用的是具有限定名称的事件。 有关更多信息,请参见路由事件概述

对于某些情况,属性名称有时是以特性的值(而不是特性名称)的形式提供的。 该属性名称还可以包括限定符,例如以所有者类型.依赖项属性名称 格式指定的属性。 在 XAML 中编写样式或模板时,此情况较为常见。 以特性值形式提供的属性名称具有不同的处理规则,这些规则由所设置的属性类型或特定 WPF 子系统的行为控制。 有关详细信息,请参见样式设置和模板化

当特性值描述属性之间的关系时,也可以使用属性名。 此功能可用于数据绑定和演示图板目标,而且由 PropertyPath 类及其类型转换器启用。 有关查找语义的更完整说明,请参见 PropertyPath XAML 语法

属性元素语法

属性元素语法是一种与元素的基本 XML 语法规则略有不同的语法。 在 XML 中,特性的值实际上是一个字符串,唯一可能的变化是使用哪种字符串编码格式。 在 XAML 中,可以指定其他对象元素作为属性的值。 此功能由属性元素语法来启用。 并不将属性指定为元素标记内的特性,而是使用元素的开始标记指定“元素类型名称.属性名称”形式的属性,在其中指定属性的值,然后结束属性元素。

具体而言,该语法以左尖括号 (<) 开头,其后紧跟包含属性元素语法的类或结构的类型名称。 类型名称后面紧跟一个点 (.),然后跟属性的名称,最后跟一个右尖括号 (>)。 对于特性语法,指定类型的已声明公共成员内必须存在该属性。 要赋给属性的值包含在相应的属性元素中。 通常,值作为一个或多个对象元素提供,因为将对象指定为值正是属性元素语法应当实现的方案。 最后,必须提供一个等效的结束标记来指定同一个元素类型名称.属性名称 组合,并与其他元素标记对形成正确的嵌套和平衡。

例如,下面的属性元素语法针对的是 Button 的 ContextMenu 属性。

XAML
<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>


当要指定的属性类型是基元值类型(如 String)或是指定了名称的枚举时,也可以用内部文本的形式给出属性元素中的值。 这两个用法在某种程度上并不常见,因为这两种情况都还可以使用更简单的特性语法。 用字符串填充属性元素的一个方案是,对于不是 XAML 内容属性但仍用于表示 UI 文本的属性,该 UI 文本中必须出现特定的空白元素(如换行符)。 特性语法不能保留换行符,但是属性元素语法可以保留换行符,不过前提是用来保留大量空白的功能处于活动状态(有关详细信息,请参见 XAML 中的空白处理)。另一个方案使 x:Uid 指令可应用于属性元素,并因此将其中的值标记为应在 WPF 输出 BAML 中本地化或通过其他技术本地化的值。

属性元素不以 WPF 逻辑树的形式表示。 属性元素不是由实例或对象支持的元素,而只是一个用来设置属性的特定语法。 (有关逻辑树概念的详细信息,请参见 WPF 中的树。)

对于同时支持特性语法和属性元素语法的属性,尽管这两种语法的细微之处(如空白处理)略有不同,但它们的结果通常是一样的。

集合语法

XAML 规范要求 XAML 处理器实现能标识其中值类型为集合的属性。 .NET 中的常规 XAML 处理器实现基于托管代码和 CLR,并且该处理器实现通过以下各项之一标识集合类型:

  • 类型实现 IList

  • 类型实现 IDictionary

  • 类型从 Array 派生(有关 XAML 中数组的更多信息,请参见 x:Array 标记扩展)。

如果属性的类型是集合,则不必在标记中以对象元素的形式指定推断的集合类型。 而要成为集合中项的元素将被指定为属性元素的一个或多个子元素。 在加载每个此类项的过程中会将该项计算为对象,然后通过调用隐含集合的 Add 方法将其添加到集合中。 例如,Style 的 Triggers 属性采用专用的集合类型 TriggerCollection(该类型实现 IList)。不必在标记中将 TriggerCollection 对象元素实例化。 而是需要在 Style.Triggers 属性元素中指定一个或多个 Trigger 项作为元素,其中 Trigger(或派生类)是一个类型,应当作为隐式强类型 TriggerCollection 的项类型。

XAML
<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>


属性可以既是一个集合类型,又是该类型和派生类型的 XAML 内容属性,本主题的下一节将讨论这种情况。

隐式集合元素在逻辑树表示形式中创建一个成员,即使该成员不以元素的形式出现在标记中也是如此。 通常,父类型的构造函数对作为其属性之一的集合执行实例化,然后最初为空的集合将成为对象树的一部分。

说明 说明

集合检测功能不支持泛型列表和字典接口(IList<T> 和 IDictionary<TKey, TValue>)。 但是,可以将 List<T> 类用作基类(因为它直接实现 IList),或者将Dictionary<TKey, TValue> 用作基类(因为它直接实现 IDictionary)。

在集合类型的 .NET 参考页中,这种特意省略集合的对象元素的语法在 XAML 语法部分中有时称为“隐式集合语法”。

除了根元素外,XAML 文件中以另一个元素的子元素形式嵌套的每个对象元素实际上都属于下列一种或两种情况:父元素的隐式集合属性的成员,或是为父元素指定 XAML 内容属性值的元素(后面的某节即将讨论 XAML 内容属性)。 换言之,一个标记页上的父元素与子元素之间的关系实际上就是一个根对象,而根对象下面的每个对象元素要么是为父元素提供属性值的一个实例,要么是同样作为父元素的集合类型属性值的集合中的一项。 这种单根概念对于 XML 很常见,并且经常在加载 XAML 的 API(例如 Load)的行为中得到加强。

下例是一种显式指定集合 (GradientStopCollection) 的对象元素的语法。

XAML
<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="Blue" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

请注意,并不总是能够显式声明集合。 例如,尝试在前面演示过的 Triggers 示例中显式声明 TriggerCollection 就会失败。 显式声明集合要求集合类必须支持默认构造函数,而TriggerCollection 没有默认构造函数。

XAML 内容属性

XAML 内容语法作为一种语法,仅在指定 ContentPropertyAttribute 作为其类声明一部分的类上启用。 ContentPropertyAttribute 引用作为该类型元素(包括派生类)的内容属性的内容名称。 当 XAML 处理器处理在对象元素的开始标记和结束标记之间找到的任何子元素或内部文本时,会向其赋予该对象的 XAML 内容属性的值。 对于内容属性允许指定显式的属性元素,但 .NET 参考的 XAML 语法章节中一般不介绍这种用法。 这种显式/详细的方法有时很实用,可使标记清晰明确或作为一种重要的标记样式,但内容属性的意图通常是要简化标记,以便可以直接嵌套直观相关的父/子元素。 对于元素上其他属性的属性元素标记,并不按严格的 XAML 语言定义将其指派为“内容”;这些标记以前是按 XAML 分析器的处理顺序进行处理的,并不将其视为“内容”。

ms788723.collapse_all(zh-cn,VS.110).gifXAML 内容属性值必须连续

XAML 内容属性的值必须完全在该对象元素的其他任何属性元素之前或之后指定。 无论将 XAML 内容属性的值指定为字符串还是指定为一个或多个对象都是如此。 例如,无法分析以下标记:

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

这在本质上是非法的,因为如果此语法是通过使用内容属性的属性元素语法而变为显式的,则内容属性将设置两次:

<Button>
  <Button.Content>I am a </Button.Content>
  <Button.Background>Blue</Button.Background>
  <Button.Content> blue button</Button.Content>
</Button>

一个类似的非法示例是,如果内容属性是一个集合,则子元素是与属性元素交错的:

<StackPanel>
  <Button>This example</Button>
  <StackPanel.Resources>
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
  </StackPanel.Resources>
  <Button>... is illegal XAML</Button>
</StackPanel>

内容属性和集合语法组合

为了接受多个对象元素作为内容,内容属性的类型必须明确地是集合类型。 与集合类型的属性元素语法相似,XAML 处理器必须标识作为集合类型的类型。 如果某个元素具有 XAML 内容属性,并且该 XAML 内容属性的类型为集合,则不需要在标记中指定隐含的集合类型作为对象元素,也不需要指定该 XAML 内容属性作为属性元素。 因此,标记中明显的内容模型现在可以将多个子元素作为指定为内容。 下面是 Panel 派生类的内容语法。 所有 Panel 派生类都证实 XAML 内容属性为 Children(它要求值为UIElementCollection 类型)。

XAML
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>


请注意,标记中既不需要 Children 的属性元素也不需要 UIElementCollection 的元素。 这是 XAML 的特有设计,其目的是为了让用于定义 UI 的递归包含元素按紧邻的父-子元素关系更直观地表示为嵌套元素的树,而不必干预属性元素标记或集合对象。 实际上,特意使 UIElementCollection 不能在标记中被显式指定为对象元素。 由于UIElementCollection 唯一的用途就是作为隐式集合,因此它不公开公共的默认构造函数,因此不能实例化为对象元素。

ms788723.collapse_all(zh-cn,VS.110).gif在具有内容属性的对象中混合使用属性元素和对象元素

XAML 规范声明 XAML 处理器可以强制用于填充某个对象元素中 XAML 内容属性的各个对象元素必须连续,并且不得混合使用。 针对混合使用属性元素和内容的这一限制由 WPF XAML 处理器强制实施。

可以将子对象元素作为某个对象元素中的第一个直接标记, 然后可以引入属性元素。 也可以指定一个或多个属性元素,接着指定内容,然后指定多个属性元素。 但是,一旦内容后面跟有属性元素,您就不能进一步引入任何内容,而只能添加属性元素。

这个内容/属性元素顺序要求不适用于用作内容的内部文本。 然而,这仍然是使内部文本保持连续的不错的标记样式,原因是,如果属性元素与内部文本交错分布,则很难直观地检测标记中的大量空白。

XAML 命名空间

上述所有语法示例均未指定默认 XAML 命名空间以外的 XAML 命名空间。 在典型的 WPF 应用程序中,将默认 XAML 命名空间指定为 WPF 命名空间。 您可以指定默认 XAML 命名空间以外的其他 XAML 命名空间,并仍然使用类似的语法。 但是,只要无法在默认 XAML 命名空间中访问已命名的类,就必须在该类名称之前加上映射到对应 CLR 命名空间的 XAML 命名空间的前缀。 例如,<custom:Example/> 是一种用于对 Example 类的实例进行实例化的对象元素语法,其中包含该类的 CLR 命名空间(可能还有包含后备类型的外部程序集信息)以前映射到 custom 前缀。

有关 XAML 命名空间的更多信息,请参见 WPF XAML 的 XAML 命名空间和命名空间映射

标记扩展

XAML 定义了一个标记扩展编程实体,该实体允许从 XAML 处理器对字符串特性值或对象元素的常规处理中进行转义,并将处理转交给后备类。 在使用特性语法时,标识 XAML 处理器的标记扩展的字符是左大括号 ({),后接右大括号 (}) 以外的任何字符。 左大括号后面的第一个字符串必须引用用来提供特定扩展行为的类,如果子字符串“Extension”是实际类名的一部分,则该引用可以省略这个子字符串。 该类后面可能会出现一个空格,该空格后面的每个字符都可以由所实现的扩展用作输入,直到遇到右大括号。

.NET XAML 实现使用 MarkupExtension 抽象类作为 WPF 以及所有其他框架或技术支持的所有标记扩展的基础。 WPF 特定实现的标记扩展通常用于提供一种方法来引用其他已经存在的对象,或者对将在运行时计算的对象进行延迟引用。 例如,通过指定用 {Binding} 标记扩展代替特定属性通常将采用的值,从而实现简单的 WPF 数据绑定。 对于无法以其他方式使用特性语法的属性,许多 WPF 标记扩展都允许使用特性语法。 例如,Style 对象是一种相对复杂的类型,其中包含一系列嵌套的对象和属性。 WPF 中的样式通常定义为 ResourceDictionary 中的资源,之后将通过请求资源的两个 WPF 标记扩展之一来引用。 标记扩展将属性值的计算推迟到查找资源时进行,并允许在特性语法中提供Style 属性的值并采用 Style 类型,如下例所示:

<Button Style="{StaticResource MyStyle}">My button</Button>

在这里,StaticResource 用来标识 StaticResourceExtension 类,该类提供标记扩展实现。 下一个字符串 MyStyle 用作非默认 StaticResourceExtension 构造函数的输入,在该构造函数中,从扩展字符串提取的参数将声明所请求的 ResourceKey MyStyle 应当是定义为资源的 Style 的 x:Key 值。 StaticResource 标记扩展 用法要求使用该资源,在加载时通过静态资源查找逻辑来提供 Style 属性值。

有关标记扩展的更多信息,请参见标记扩展和 WPF XAML。 有关常规 .NET XAML 实现中启用的标记扩展和其他 XAML 编程功能的参考,请参见 XAML 命名空间 (x:) 语言功能 有关特定于 WPF 的标记扩展,请参见 WPF XAML 扩展

附加属性

附加属性是 XAML 中引入的一个编程概念,借此,特定类型可以拥有和定义属性,但在任何元素上都将属性设置为特性或属性元素。 附加属性所面向的主要方案是,允许标记结构中的子元素向父元素报告信息,同时不需要在所有元素之间广泛共享的对象模型。 相反,附加属性可以由任何父元素用来向子元素报告信息。 有关附加属性的用途以及如何创建您自己的附加属性的更多信息,请参见附加属性概述

附加属性使用的语法在表面上与属性元素语法非常相似,因为您还需要指定类型名.属性名 组合。 二者有两个重要的差异:

  • 即使在通过特性语法设置附加属性时,也可以使用类型名.属性名 组合。 只有附加属性才要求特性语法中使用限定属性名。

  • 对于附加属性还可以使用属性元素语法。 但是,对于典型的属性元素语法,您指定的类型名 是包含属性元素的对象元素。 如果您引用的是附加属性,则类型名 是用来定义附加属性的类,而不是包含对象元素。

附加事件

附加事件是 XAML 中引入的另一个编程概念,其中可以由特定类型定义事件,但处理程序可以附加到任何对象元素上。 在 WPF 实现中,用于定义附加事件的类型通常是用于定义服务的静态类型,而这些附加事件有时由用于公开服务的类型中的路由事件别名公开。 附加事件的处理程序是通过特性语法指定的。 就附加事件而言,特性语法针对附加事件进行了扩展,以便允许“类型名称.事件名称”用法,其中“类型名称”是为附加事件基础结构提供 Add 和 Remove 事件处理程序访问器的类,而“事件名称”是事件名称。

XAML 根元素剖析

下表显示了一个经过分解的典型 XAML 根元素,同时显示了根元素的具体特性:

<Page

根元素的开始对象元素

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

默认 (WPF) XAML 命名空间

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

XAML 语言 XAML 命名空间

x:Class="ExampleNamespace.ExampleCode"

分部类声明,它将标记连接到为分部类定义的任何代码隐藏

>

根的对象元素的末尾。 由于该元素包含子元素,因此对象未结束

可选的和不建议的 XAML 用法

以下各节描述 XAML 处理器在技术上支持的 XAML 用法,但这些用法会产生冗长的内容或其他美观上的问题,当您开发包含 XAML 源的应用程序时,这些问题会对保持可读的 XAML 文件产生影响。

ms788723.collapse_all(zh-cn,VS.110).gif属性元素的可选用法

属性元素的可选用法包括,显式写入被 XAML 处理器视为隐式的元素内容属性。 例如,声明 Menu 的内容时,可以选择将 Menu 的 Items 集合显式声明为 <Menu.Items> 属性元素标记,并将每个 MenuItem 放置在 <Menu.Items> 中,而不是使用隐式 XAML 处理器行为(即,Menu 的所有子元素都必须是 MenuItem 而且放置在 Items 集合中)。 有时,这个可选用法可以帮助以可视方式阐明标记中所表示的对象结构。 或者,属性元素的隐式用法有时可以避免使用在技术上具有功能,但在视觉上容易引起混淆(如在特性值中嵌套标记扩展)的标记。

ms788723.collapse_all(zh-cn,VS.110).giftypeName.memberName 全限定特性

使用特性的类型名称.成员名称 格式实际上比仅仅使用路由事件的情况更为普遍。 但是,在其他情况下,如果只是为了实现标记样式和可读性,则该格式是多余的,您应当避免使用它。 在下面的示例中,对 Background 特性的三个引用是完全等效的:

XAML
<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>


Button.Background 之所以适用,是因为在 Button 上对该属性的限定查找获得成功(Background 从 Control 继承而来),而且 Button 是对象元素的类或者基类。Control.Background 之所以适用,是因为 Control 类实际定义了 Background,而且 Control 是 Button 的基类。

但是,下面的类型名.成员名 格式示例并不适用,因此显示为已注释掉:

XAML
<!--<Button Label.Background="Blue">Does not work</Button> -->


Label 是 Control 的另一个派生类,而且,如果在 Label 对象元素中指定了 Label.Background,则该用法将适用。 但是,由于 Label 不是 Button 的类或基类,因此指定的 XAML 处理器行为是随后将 Label.Background 作为附加属性进行处理。 Label.Background 不是可用的附加属性,因此这个用法将失败。

ms788723.collapse_all(zh-cn,VS.110).gifbaseTypeName.memberName 属性元素

与“类型名称.成员名称”格式如何适用于特性语法类似,“基类型名称.成员名称”语法适用于属性元素语法。 例如,下面的语法适用:

XAML
<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>


在这里,即使属性元素包含在 Button 中,属性元素也会以 Control.Background 形式提供。

但是,正如特性的“类型名称.成员名称”形式一样,“基类型.成员名称”在标记中不是良好的样式,应当避免使用这种形式。