XAML 语法详述

本主题定义用于描述 XAML 语法元素的术语。 这些术语在本说明的其余部分被频繁使用,特别是在 WPF 文档中,以及在使用 XAML 或基于 System.Xaml 级别的 XAML 语言支持启用基本 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 类型系统构建。 XAML 类型映射到 CLR 类型,以便在分析 WPF 的 XAML 时实例化运行时表示形式。 因此,本文档中语法的其余讨论将包含对 CLR 类型系统的引用,而 XAML 语言规范中的等效语法讨论则不包括。 (根据 XAML 语言规范级别,XAML 类型可以映射到任何其他类型系统,这不必是 CLR,但需要创建和使用其他 XAML 分析器。

类型和类继承的成员

属性和事件作为 WPF 类型的 XAML 成员出现时,通常继承自基类型。 例如,请考虑以下示例: <Button Background="Blue" .../> 查看类定义、反射结果或文档时,Background 属性并不是直接在 Button 类上声明的属性。 Background而是继承自基Control类。

WPF XAML 元素的类继承行为与 XML 标记的架构强制解释有很大区别。 类继承可能变得复杂,尤其是在中间基类是抽象的,或者涉及接口时。 这是因为 XAML 元素集合及其允许的属性难以通过通常用于 XML 编程的架构类型(如 DTD 或 XSD 格式)准确完整地表示。 另一个原因是 XAML 语言本身的扩展性和类型映射功能排除了允许类型和成员的任何固定表示形式的完整性。

Object 元素语法

对象元素语法 是 XAML 标记语法,通过声明 XML 元素来实例化 CLR 类或结构。 此语法类似于其他标记语言(如 HTML)的元素语法。 对象元素语法以左尖括号(<)开头,后跟要实例化的类或结构的类型名称。 零个或多个空格可以遵循类型名称,零个或多个属性也可以声明在对象元素上,其中一个或多个空格分隔每个属性名称=“value”对。 最后,以下项之一必须为真:

  • 元素和标记必须由正斜杠(/)紧跟右尖括号(>)关闭。

  • 开始标记必须由右角括号 (>) 完成。 其他对象元素、属性元素或内部文本可以遵循开始标记。 此处可能包含的内容通常受元素的对象模型的约束。 对象元素的等效结束标记必须存在,并且必须与其他开始和结束标记对以适当的嵌套和平衡形式存在。

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

例如,以下示例展示了对象元素语法,通过这种语法可以实例化 Button 类的一个新实例,并指定一个 Name 属性及其对应的值。

<Button Name="CheckoutButton"/>

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

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

内容模型

一个类可能在语法上支持作为 XAML 对象元素的使用,但只有当该元素被放置在整个内容模型或元素树的预期位置时,它才能在应用程序或页面中正常运行。 例如, MenuItem 通常只应作为派生类的 MenuBase 子级放置,例如 Menu。 特定元素的内容模型在控件和其他能够用作 XAML 元素的 WPF 类的类页面备注中有所记录。

对象元素的属性

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

通过设置属性的值,可以向对象添加特征或特征,因为它们存在于运行时对象图中。 对象元素中创建的对象的初始状态基于无参数构造函数行为。 通常,应用程序将使用任何给定对象的完全默认实例以外的内容。

属性语法(特性)

属性语法是 XAML 标记语法,它通过对现有对象元素声明属性来设置属性的值。 属性名称必须与类中支持相关对象元素的属性的 CLR 成员名称匹配。 属性名称后跟赋值运算符(=)。 属性值必须是括在引号中的字符串。

注释

可以使用交替引号在属性中放置文本引号。 例如,可以将单引号用作声明包含双引号字符的字符串的方法。 无论是使用单引号还是双引号,都应使用匹配对来打开和关闭属性值字符串。 还有一些转义序列或其他技术可用于处理任何特定 XAML 语法施加的字符限制。 请参阅 XML 字符实体和 XAML

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

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

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

属性值的处理

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

使用以下处理顺序之一填充属性值:

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

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

  3. 如果没有TypeConverter,则尝试直接转换为属性类型。 最后一个级别是在 XAML 语言基元类型之间直接转换解析器原生的值,或检查枚举中具名常量的名称(然后解析器访问匹配的值)。

枚举属性值

XAML 中的枚举由 XAML 分析程序以固有方式进行处理,应通过指定枚举命名常量之一的字符串名称来指定枚举的成员。

对于非标志枚举值,本机行为是处理属性值的字符串并将其解析为枚举值之一。 您没有像在代码中那样以枚举.格式指定枚举。 您只需指定 ,而 枚举 将根据您设置的属性类型来推断。 如果以 枚举. 的形式指定属性,它将无法正确解析。

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

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

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

属性和事件成员名称引用

指定属性时,可以引用任何属于您为包含对象元素实例化的 CLR 类型的属性或事件。

或者,可以引用附加属性或附加事件,与包含的对象元素无关。 (后续部分将讨论附加属性。

可以使用 typeName.event 部分限定名称为可通过默认命名空间访问的任何对象命名事件;此语法支持附加处理程序,以处理来自子元素的路由事件,而父元素在其成员列表中并没有该事件。 此语法类似于附加事件语法,但此处的事件不是真正的附加事件。 而是引用具有限定名称的事件。 有关详细信息,请参阅 路由事件概述

在某些情况下,属性名称有时作为属性值提供,而不是以属性名称形式提供。 该属性名称还可以包含限定符,例如表单 ownerType 中指定的属性。dependencyPropertyName。 在 XAML 中编写样式或模板时,这种情况很常见。 作为属性值提供的属性名称的处理规则不同,并受所设置的属性的类型或特定 WPF 子系统的行为的约束。 有关详细信息,请参阅 样式设置和模板化

属性名称的另一个用法是当属性值描述属性属性关系时。 此功能用于数据绑定和情节提要目标,且通过 PropertyPath 类及其类型转换器启用。 有关查找语义的更完整说明,请参阅 PropertyPath XAML 语法

Property 元素语法

属性元素语法 是一种语法,与元素的基本 XML 语法规则有些不同。 在 XML 中,属性的值是一个事实上的字符串,唯一可能的变体是使用字符串编码格式。 在 XAML 中,可以将其他对象元素指定为属性的值。 通过属性元素语法启用此功能。 该属性不是在元素标记中指定为属性,而是使用 elementTypeName 中的开始元素标记来指定属性。propertyName 窗体中指定了属性的值,然后关闭属性元素。

具体而言,语法以左尖括号(<)开头,紧跟属性元素语法所包含的类或结构的类型名称。 紧接着是一个点(.),然后是属性的名称,然后是右尖括号(>)。 与特性语法一样,该属性必须存在于指定类型的声明的公共成员中。 要分配给该属性的值包含在属性元素中。 通常,该值作为一个或多个对象元素提供,因为将对象指定为值是属性元素语法旨在解决的方案。 最后,必须提供指定相同elementTypeName.propertyName组合的等效结束标记,其嵌套应适当,并与其他元素标记保持平衡。

例如,下面是ButtonContextMenu属性元素语法。

<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,并通过以下方法之一标识集合类型:

如果属性的类型是集合,则推断的集合类型不需要在标记中指定为对象元素。 相反,要成为集合中的项的元素被指定为属性元素的一个或多个子元素。 每个此类项在加载过程中评估为对象,并通过调用 Add 隐式集合的方法添加到集合中。 例如,StyleTriggers属性使用实现IList的专用集合类型TriggerCollection。 不需要在标记中实例化 TriggerCollection 对象元素。 相反,您应将一个或多个 Trigger 项指定为 Style.Triggers 属性元素中的元素,其中 Trigger(或派生类)是针对强类型和隐式 TriggerCollection 所期望的项类型。

<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> 类用作基类,因为它直接实现 IListDictionary<TKey,TValue> 作为基类,因为它直接实现 IDictionary

在 .NET 集合类型参考页中,在 XAML 语法部分,此语法偶尔被标注为故意省略集合的对象元素,称为隐式集合语法。

除根元素外,嵌套为另一个元素的子元素的 XAML 文件中的每个对象元素实际上都是下列一个或两个情况中的元素:其父元素的隐式集合属性的成员,或指定父元素 XAML 内容属性的值的元素(即将在一节中讨论 XAML 内容属性)。 换句话说,标记页中父元素和子元素的关系实际上是一个在根节点上的单个对象,根节点下的每个对象元素要么是提供父级属性值的单个实例,要么是集合中的某个项目,该集合也是父级的一个集合类型属性值。 此单根概念与 XML 很常见,在加载 XAML 的 LoadAPI 行为中经常得到强化。

下面的示例是一个语法,其中包含显式指定的集合 (GradientStopCollection) 的对象元素。

<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 语言定义分配为“content” ;它们以前在 XAML 分析器处理顺序中进行处理,不被视为“内容”。

XAML 内容属性值必须是连续的

必须在其他属性元素之前或之后完全提供该对象元素上的 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 的值。

<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 因此不会公开公共无参数构造函数,因此不能实例化为对象元素。

在具有 Content 属性的对象中混合属性元素和对象元素

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 处理器标记扩展的字符是左大括号({),后面跟着任意字符,但不能是右大括号(})。 左大括号后面的第一个字符串必须引用提供特定扩展行为的类,如果该子字符串是 true 类名的一部分,则引用可能会省略子字符串“Extension”。 此后,可能会出现一个空格,然后扩展实现将每个后续字符用作输入,直到遇到右大括号为止。

.NET XAML 实现使用 MarkupExtension 抽象类作为 WPF 支持的所有标记扩展以及其他框架或技术的基础。 WPF 专门实现的标记扩展通常旨在提供引用其他现有对象的方法,或对将在运行时评估的对象进行延迟引用。 例如,通过指定 {Binding} 标记扩展代替特定属性通常采用的值来完成简单的 WPF 数据绑定。 许多 WPF 标记扩展启用了一种属性语法,使得在其他情况下无法实现的属性语法得以应用。 例如,对象 Style 是一种相对复杂的类型,其中包含嵌套的一系列对象和属性。 在 WPF 中,样式通常被定义为 ResourceDictionary 中的资源,然后通过请求资源的两种 WPF 标记扩展之一进行引用。 标记扩展将属性值的计算延后到资源查找阶段,并允许通过以下示例中的属性语法提供类型为 StyleStyle 属性值。

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

此处,StaticResource 标识提供标记扩展实现的 StaticResourceExtension 类。 下一个字符串 MyStyle 被用作非默认 StaticResourceExtension 构造函数的输入,其中从扩展字符串中提取的参数声明所需的 ResourceKeyMyStyle 被期望是作为资源定义的 Stylex:Key 值。 StaticResource 标记扩展使用请求资源在加载时通过静态资源查找逻辑提供Style属性值。

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

附加属性

附加属性是在 XAML 中引入的编程概念,其中属性可以由特定类型来拥有和定义,但可以在任何元素上作为属性或属性元素进行设置。 附加属性的主要方案是使标记结构中的子元素能够向父元素报告信息,而无需跨所有元素广泛共享对象模型。 相反,父元素可以使用附加属性向子元素报告信息。 有关附加属性的用途以及如何创建自己的附加属性的详细信息,请参阅 “附加属性概述”。

附加属性使用一种在表面上类似于属性元素语法的语法,此语法中,你还需指定 typeName.propertyName 组合。 有两个重要区别:

  • 可以使用 typeName。即使通过属性语法设置附加属性,propertyName 组合也是如此。 附加属性是唯一需要在属性语法中限定属性名称的情况。

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

附加活动

附加事件是 XAML 中引入的另一个编程概念,其中事件可由特定类型定义,但处理程序可以附加到任何对象元素上。 在 WOF 实现中,定义附加事件的类型通常是一个定义服务的静态类型,有时这些附加事件通过在提供服务的类型中定义的路由事件别名公开。 附加事件的处理程序是通过属性语法指定的。 与附加事件一样,附加事件的属性语法将扩展为允许 typeNameeventName 用法,其中 typeName 是为附加事件基础结构提供 AddRemove 事件处理程序访问器的类, eventName 是事件名称。

XAML 根元素剖析

下表显示了典型的 XAML 根元素分解,其中显示了根元素的特定属性:

特征 DESCRIPTION
<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 源的应用程序时的人可读性。

可选属性元素用法

可选属性元素用法包括显式写出 XAML 处理器认为隐式的元素内容属性。 例如,当你声明Menu的内容时,可以选择将Menu集合显式声明为<Menu.Items>属性元素标记,并将每个MenuItem元素放置在<Menu.Items>中,而不是使用 XAML 处理器的隐式行为,即Menu的所有子元素必须是MenuItem类型,并放置在Items集合中。 有时,可选用法有助于直观地阐明标记中表示的对象结构。 或者,有时显式属性元素用法可以避免在技术上正常运行但视觉上令人困惑的标记,例如属性值中的嵌套标记扩展。

完整的 typeName.memberName 限定属性

typeName.memberName 的格式用于属性实际上比仅用于路由事件的情况更具有普适性。 在某些情况下,那种形式是多余的,你应该避免使用,即便只是为了标记样式和可读性的原因。 在以下示例中,三次对Background属性的引用完全等效:

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

由于对Button 属性的限定查找成功(Background 是从Control继承来的),Button.Background 可以正常工作,并且Button 是对象元素的类或其基类。 Control.Background 工作是因为该 Control 类实际定义 Background 并且 Control 是基 Button 类。

但是,以下 typeName.memberName 表单示例不起作用,因此以注释的形式显示。

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

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

baseTypeName.memberName 属性元素

以类似于 typeName.memberName 语法用于属性语法的方式,baseTypeName.memberName 语法用于属性元素语法。 例如,以下语法有效:

<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>

此处,属性元素被指定为 Control.Background 即使属性元素包含在内 Button

但是 typeName.memberName 用于属性的形式,以及 baseTypeName.memberName 在标记中的使用风格不佳,所以应避免这样做。

另请参阅