本主题介绍可扩展应用程序标记语言 (XAML) 语言的功能并演示如何使用 XAML 编写 Windows Presentation Foundation (WPF) 应用程序本主题专门介绍了 Windows Presentation Foundation (WPF) 实现的 XAMLXAML 本身是比 Windows Presentation Foundation (WPF) 更广泛的一个语言概念 具有流控制支持的声明性语言XAML 简化了为 NET Framework 编程模型创建 UI 的过程您可以在声明性 XAML 标记中创建可见的 UI 元素然后使用代码隐藏文件(通过分部类定义与标记相连接)将 UI 定义与运行时逻辑相分离在 XAML 中混合代码和标记的功能很重要因为 XML 本身是声明性的不会为流控制真正建议一个模型基于 XML 的声明性语言非常直观可以为用户(尤其是具有 Web 设计和技术背景的人员)创建从原型到生产的各种界面与其他大多数标记语言不同XAML 直接呈现托管对象的实例化这种常规设计原则简化了使用 XAML 创建的对象的代码和调试访问 XAML 文件是指通常使用 xaml 扩展名的 XML 文件 下面的 XAML 示例演示了小标记在创建作为 UI 一部分的按钮时的必要性创建的按钮通过主题样式获得默认的可视化表示形式通过其类设计获得默认的行为 )thisstylewidth=; border= twffan=done> XAML 对象元素 XAML 有一组规则这些规则将对象元素映射为类或结构将属性 (Attribute) 映射为属性 (Property) 或事件并将 XML 命名空间映射为 CLR 命名空间XAML 元素映射为被引用程序集中定义的 Microsoft NET 类型而属性 (Attribute) 则映射为这些类型的成员 上面的示例指定了两个对象元素<STACKPANEL>(具有一个结束标记)和<BUTTON>同样具有多个属性下一节将介绍属性)字符串 StackPanel 和 Button 都将映射为某个类的名称该类由 WPF 定义并且是 WPF 程序集的一部分在指定对象元素标记时可以为 XAML 处理创建一条指令以便在加载 XAML 页时创建指定类的一个新实例每个实例都是通过调用基础类或结构的默认构造函数并对结果进行存储而创建的为了可用作 XAML 中的对象元素该类或结构必须公开一个公共的默认(无参数)构造函数 设置属性 XAML 中的属性是通过使用各种可能的语法在对象元素上设置属性来设置的根据所设置的属性的特征给定属性可使用的语法会有所不同 通过设置属性值可以为对象元素添加功能或特征对象元素的基础对象实例的初始状态基于默认的构造函数行为通常您的应用程序将使用其他一些实例而不是任何给定对象的完全默认的实例 属性语法 在 XAML 中属性 (Property) 常常可以表示为属性 (Attribute)属性 (Attribute) 语法是最简单的属性 (Property) 设置语法并将成为过去使用标记语言的开发人员可以使用的最直观的语法例如以下标记将创建一个具有红色文本和蓝色背景的按钮还会创建指定为 Content 的显示文本 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 属性元素语法 对于一个对象元素的某些属性 (Property)属性 (Attribute) 语法是不可能实现的因为提供属性 (Property) 值所需的对象或信息不能充分地表示为简单的字符串对于这些情况可以使用另一个语法即属性元素语法属性元素语法用标记的内容设置包含元素的引用的属性一般而言内容就是作为属性值的类型的某个对象(值设置实例通常被指定为另一个对象元素)属性元素本身的语法为 <类型名称属性>指定内容之后必须用一个结束标记结束属性元素就像其他任何元素(语法为 类型名称属性>)一样对于同时支持属性 (Attribute) 和属性 (Property) 元素语法的属性 (Property)尽管这两种语法的细微之处(如空白处理)略有不同但它们的结果通常是一样的如果可以使用属性 (Attribute) 语法那么使用属性 (Attribute) 语法通常更为方便且能够实现更为精简的标记但这只是一个风格的问题而不属于技术限制下面的示例演示了在前面的属性 (Attribute) 语法示例中设置的相同属性 (Property)但这次对 Button 的所有属性 (Property) 使用了属性 (Property) 元素语法 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> XAML 的属性 (Property) 元素语法表示了与标记的基本 XML 解释之间的巨大背离对于 XML<类型名称属性> 代表了另一个元素该元素仅表示一个子元素而与 TypeName 父级之间没有必然的隐含关系在 XAML 中<类型名称Property> 直接表示 Property 是类型名称 的属性(由属性元素内容设置)而绝不会是一个名称相似(碰巧名称中有一个点)但却截然不同的元素 属性和类继承 作为 WPF 元素的XAML 属性 (Attribute) 而出现的属性 (Property) 通常从基类继承而来例如在上一个示例中如果您要查看类定义反射结果或文档Background 属性并不是在 Button 类上直接声明的属性相反Background 是从基 Control 类继承而来 WPF XAML 元素的类继承行为是与标记的基本 XML 解释之间的另一个巨大背离使用类继承(尤其是中间基类为抽象类时)的另一个原因在于通过 XML 编程常用的架构类型(如 DTD 或 XSD 格式)几乎不可能准确且完整地表示 XAML 元素及其允许属性集另外XAML 中的X表示extensible(可扩展)而可扩展性破坏了什么是用于 WPF 的 XAML的任何给定表示形式的完整性
引用值和标记扩展 标记扩展是一个 XAML 概念在属性语法中花括号({ 和 })表示标记扩展用法 此用法指示 XAML 处理不要像通常那样将属性值视为一个字符串或者可直接转换为文本字符串的值 当属性采用引用类型值时这些属性常常需要属性元素语法(始终创建一个新实例)或通过标记扩展的对象引用标记扩展用法有可能会返回现有实例因此可以更加多样化或者产生较少的对象系统开销 当使用标记扩展提供属性值时应改为由相关标记扩展的后备类中的逻辑提供属性值WPF 应用程序编程中最常用的标记扩展是 Binding(用于数据绑定表达式)以及资源引用 StaticResource 和 DynamicResource通过使用标记扩展即使属性 (Property) 不支持对直接对象实例化使用属性 (Attribute) 语法也可以使用属性 (Attribute) 语法为属性 (Property) 提供引用值或者使特定行为能够符合必须用属性 (Property) 类型值填充 XAML 属性 (Property) 这一常规行为要求 例如下面的示例使用属性 (Attribute) 语法设置 Style 属性 (Property) 的值Style 属性 (Property) 采用了 Style 类的一个实例这是默认情况下不能在属性 (Attribute) 语法字符串中指定的引用类型但在本例中属性 (Attribute) 引用了特定的标记扩展 StaticResource当处理该标记扩展时它返回对以前在资源字典中作为键控资源进行实例化的某个样式的引用 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 资源只是 WPF 或 XAML 启用的一种标记扩展用法 支持 Typeconverter 的属性值 在属性语法一节中曾提到属性值必须能够使用字符串进行设置对字符串如何转换为其他对象类型或基元值的基本本机处理取决于 String 类型本身但是很多 WPF 类型或这些类型的成员扩展了基本字符串属性处理行为因此更复杂的对象类型的实例可通过字符串指定为属性值在代码级别此处理是通过指定处理字符串属性值的 CLR 类型转换器来完成的常用于指示矩形区域尺寸(如 Margin)的 Thickness 结构类型是这样一个类型的示例它具有针对采用该类型的所有属性 (Property) 公开的一个特殊的支持类型转换器的属性 (Attribute) 语法以便于在 XAML 标记中使用下面的示例使用支持类型转换器的属性 (Attribute) 语法来为 Margin 提供值 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 上面的属性 (Attribute) 语法示例与下面更为详细的语法示例等效但在下面的示例中Margin 是通过包含 Thickness 对象元素的属性 (Property) 元素语法设置的而且 Thickness 的四个关键属性 (Property) 设置为新实例的属性 (Attribute) image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 是使用支持类型转换器的语法还是使用更详细的等效语法通常只是编码风格的选择问题但支持转换器的语法有助于生成更简洁的标记(但是有一些对象只能采用类型转换器将属性设置为该类型因为类型对象本身并没有默认的构造函数例如Cursor) 集合类型和 XAML 集合属性 XAML 指定了一个语言功能通过该功能可以从标记中特意省略表示集合类型的对象元素当 XAML 处理器处理采用了集合类型的属性时将隐式创建相应集合类型的实例即使标记中不存在该集合的对象元素也是如此在集合类型的 SDK 参考页中特意省略集合对象元素的这种语法在 XAML 语法部分中有时候称为隐式集合语法 隐式集合语法适用于实现 IList 或 IDictionary 的类型或者适用于数组 您已经在 XAML 资源示例中看到了未调用的集合对象元素的隐式集合语法的示例 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 除了根元素外页面上作为另一个元素的子元素而嵌套的每个对象元素实际上都是下列一种或两种情况下的元素父元素的隐式集合属性的一个成员或者为父元素指定 XAML 内容属性值的元素(XAML 内容属性将在下一节进行讨论)换言之一个标记页上的父元素与子元素之间的关系实际上就是一个根对象而根对象下面的每个对象元素要么是为父元素提供属性值的一个实例要么是同样作为父元素的集合类型属性值的集合中的一项在资源示例的案例中Resources 属性采用 ResourceDictionary 类型的一个对象 下面的示例在语法上与显式指定的 ResourceDictionary 的对象元素等效 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> Resources 集合是许多常见的 WPF 框架级元素上存在的集合属性的一个示例在 XAML 中设置此属性需要使用属性元素语法属性元素中的每个被包含的对象元素都成为集合(IDictionary 实现)中的一个项虽然集合类型本身通常没有包含项的属性或索引器但是该属性不能在标记中指定它完全是隐含的对于 ResourceDictionary该属性是 Item 索引器 XAML 内容属性 XAML 指定了一个语言功能通过该功能任何可以用作 XAML 对象元素的类都可以确切指定其属性之一作为该类实例的 XAML 内容属性当 XAML 处理器处理具有 XAML 内容属性的对象元素时该对象元素的任何 XML 子元素都被当作包含在一个表示该内容属性的隐式属性元素标记中来处理在标记中可以省略 XAML 内容属性的属性元素语法在标记中指定的任何子元素都将成为 XAML 内容属性的值 您已经看过了未调用的 XAML 内容属性的示例本主题中的第一个示例 这里Button 是 StackPanel 的子元素这是一个简单直观的标记其中出于两个不同的原因省略了两个标记 省略的 StackPanelChildren 属性元素 StackPanel 从 Panel 派生Panel 将 Panel……Children 定义为其 XAML 内容属性Panel 的所有派生类因而具有该 XAML 内容属性而 Panel……Children 的属性元素可省略 省略的 UIElementCollection 对象元素 Panel……Children 属性采用类型 UIElementCollection该类型实现 IList因此根据为集合定义的 XAML 规则可以省略 UIElementCollection 对象元素标记在这种情况下UIElementCollection 实际上不能实例化为一个对象元素您甚至无法显式声明该集合对象这是因为 UIElementCollection 不公开默认的构造函数其他几个 WPF 集合类型也不公开对象元素用法的构造函数因为 XAML 集合语法处理仍然允许它们在 XAML 中隐式工作这就是 UIElementCollection 对象元素在示例中显示为已被注释的原因如果未被注释示例将不能编译 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 内部文本和 XAML 内容属性 StackPanel / Button 示例还有另一种变体 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 请注意为 Button 指定的显示文本如何发生变化前面已在属性 (Attribute) 语法中指定了 Content 属性 (Property)这次显示字符串是 Button 对象元素中的内部文本此语法可行因为 Content 是 Button 基类 ContentControl 的 XAML 内容属性元素中的字符串根据 Content 属性的属性类型(即 Object)进行计算Object 不会尝试任何字符串类型转换因此 Content 属性的值变成了文本字符串值或者Button 中的内容可以是任何单个 ObjectButton 等控件通常为类定义 XAML 内容属性因此 XAML 内容属性可用于 UI 和显示文本或用于控件合成或同时用于此两者 对于流程文档模型和本地化而言在元素中放置字符串作为内容以生成与其他常见标记语言类似的标记的功能特别重要 XAML 内容属性值必须连续 XAML 内容属性的值必须完全在该对象元素的其他任何属性元素之前或之后指定不管 XAML 内容属性的值指定为字符串还是指定为一个或多个对象都是如此例如下面的标记无法进行编译 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 这在本质上是非法的因为如果此语法是通过使用内容属性的属性元素语法而变为显式的则内容属性将设置两次 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 一个类似的非法示例是如果内容属性是一个集合则子元素是与属性元素交错的 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 内容模型 从语法上讲可能支持将类用作 XAML 元素但只有放置到整体内容模型或元素树中的所需位置时该元素才能在应用程序或页面上正常运行例如MenuItem 通常只应作为 MenuBase 派生类(如 Menu)的子级放置特定元素的内容模型在可用作 XAML 元素的控件和其他 WPF 类的类页面上的备注中进行说明对于具有更复杂内容模型的某些控件内容模型作为单独的概念主题进行说明 XAML 中的大小写和空白 XAML 区分大小写按名称与程序集中的基础类型进行比较或者与类型的成员进行比较时必须使用正确的大小写指定所有对象元素属性 (Property) 元素和属性 (Attribute) 名称属性的值并不总是区分大小写值是否区分大小写将取决于与采用该值的属性关联的类型转换器行为或取决于属性值类型例如采用 Boolean 类型的属性可以采用 true 或 True 作为等效值但只是因为 Boolean 的默认字符串类型转换已经允许这些值作为等效值 XAML 处理器和序列化程序将忽略或删除所有无意义的空白并规范化任何有意义的空白只有当您在 XAML 内容属性中指定字符串时才会体现此行为的重要性简言之XAML 将空格换行符和制表符转化为空格如果它们出现在一个连续字符串的任一端则保留一个空格 有关 XAML 语法的更多信息 隐式集合语法和 XAML 内容属性都是允许省略某些推断标记的 XAML 语言功能 这些功能的目的是在编写或检查标记时使页面上的元素的父子关系更明显 如果您正在创建自定义类并且正在考虑是否允许使用 XAMLXAML 语法术语主题也是一个很好的起点 XAML 根元素和 xmlns 一个 XAML 文件只能有一个根元素这样才能成为格式正确的 XML 文件和有效的 XAML 文件通常应选择属于应用程序模型一部分的元素(例如为页面选择 Window 或 Page为外部字典选择 ResourceDictionary或为应用程序定义根选择 Application)下面的示例演示 WPF 页面的典型 XAML 文件的根元素其中的根元素为 Page image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 根元素还包含属性 xmlns 和 xmlns:x这些属性向 XAML 处理器指明哪些命名空间包含标记将要引用的元素的元素定义xmlns 属性专门指示默认的 xmlns 命名空间在默认的 xmlns 命名空间中可以不使用前缀指定标记中的对象元素对于大多数 WPF 应用程序方案以及 SDK 的 WPF 部分中给出的几乎所有示例默认的 xmlns 命名空间均映射为 WPF 命名空间 xmlns:x 属性指示另外一个 xmlns 命名空间该命名空间映射 XAML 语言命名空间 在具有此映射的文件的标记中引用时XAML 规范定义的必需语言组件带有 x: 前缀使用 xmlns 定义用法范围和映射的这种做法符合 XML 规范请注意xmlns 属性仅在每页的根元素上和应用程序定义上(如果在标记中提供了应用程序定义)才是严格必需的xmlns 定义将应用于根的所有子元素(此行为仍然符合 xmlns 的 XML 规范)xmlns 属性还允许出现在根下面的其他元素上并且将应用于定义元素的任何子元素但是此用法并不典型因为频繁定义或重新定义 xmlns 命名空间可能会导致 XAML 标记样式难以阅读 由于存在属于项目生成文件一部分的配置因此可以知道 WPF 程序集包含的某些类型支持 WPF 到默认 xmlns 的映射程序集还映射到目标文件中因此为了引用来自 WPF 程序集的 XAML 元素只需映射 xmlns 即可对于您自己的自定义程序集或者除 WPF 之外的程序集可以将该程序集指定为 xmlns 映射的一部分通常可选择其他前缀但是也可以选择其他 xmlns 作为默认值然后将 WPF 映射到前缀 x: 前缀 在前面的根元素示例中前缀 x 用于映射 XAML xmlns 在此 SDK 的项目模板示例以及文档中此 x 前缀将用于映射 XAML xmlnsx 前缀/XAML xmlns 包含多个将在 XAML 中频繁用到的编程构造下面列出了将用到的最常见 x 前缀/XAML xmlns 编程构造xKey为 ResourceDictionary 中的每个资源设置一个唯一的键在应用程序标记中看到的所有 x 用法中xKey 可能占到 % xClass向为 XAML 页提供代码隐藏的类指定 CLR 命名空间和类名必须具有这样一个类才能支持代码隐藏也正是由于这个原因即使没有资源您也几乎总是会看到映射的 x xName处理对象元素后为运行时代码中存在的实例指定运行时对象名称在不支持等效的 WPF 框架级Name 属性的情况下命名元素时可以使用 xName某些动画方案中会发生这种情况 xStatic启用一个获取静态值的值引用该静态值只能是一个 XAML 可设置属性 xType根据类型名称构造一个 Type 引用它用于指定采用 Type 的属性 (Attribute)如 Style……TargetType不过在许多情况下属性 (Property) 本身具有字符串到 Type 的转换功能因此使用 xType 是可选的 x 前缀/XAML xmlns 中还有其他一些不太常见的编程构造 事件和 XAML 代码隐藏 大多数 WPF 应用程序都是既包括标记又包括代码隐藏在一个项目中XAML 被编写为 xaml 文件而使用 CLR 语言(如 Microsoft Visual Basic NET 或 C#)编写代码隐藏文件编译 XAML 文件时每个 XAML 页的 XAML 代码隐藏文件的位置是通过指定一个命名空间和类作为 XAML 页的根元素的 x:Class 属性来确定的 在目前已介绍的示例中您已看到几个按钮但还没有一个按钮具有任何关联的逻辑行为为对象元素添加行为的主要应用程序级机制是使用元素类的现有事件并为在运行时引发该事件时调用的该事件编写特定的处理程序事件名称以及要使用的处理程序的名称在标记中指定而实现处理程序的代码在代码隐藏中定义 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 请注意代码隐藏文件使用命名空间 MyNamespace 并将 MyPageCode 声明为该命名空间内的一个分部类这相当于在标记根中提供的 MyNamespaceMyPageCode 的 x:Class 属性值编译器将通过从根元素类型派生一个类自动为编译的任何 XAML 页创建一个分部类当您提供也会定义同一分部类的代码隐藏时将在与编译的应用程序相同的命名空间和类中组合生成的代码 如果您不想创建单独的代码隐藏文件还可以将代码内联到 XAML 文件中但是内联代码是一种缺少多样性的方法有很多的限制 事件属性语法 当您在标记中通过事件指定行为时通常使用属性语法来附加处理程序在其中指定事件属性的对象元素则变成侦听事件以及调用处理程序的实例您要处理的具体事件的名称是属性名属性值是您要定义的处理程序的方法名然后您必须在代码隐藏中提供处理程序实现并使处理程序基于该事件的委托您使用编程语言(如 Microsoft Visual Basic NET 或 C#)在代码隐藏中编写处理程序 引发事件时每个 WPF 事件都将报告事件数据事件处理程序可以访问这些事件数据在前面的示例中处理程序通过事件数据获取所报告的事件源然后在该事件源上设置属性 路由事件 路由事件是一个特殊的事件功能该功能是 WPF 特有的并且是它的基础路由事件允许一个元素处理另一个元素引发的事件只要这些元素通过元素树关系连接起来当使用 XAML 属性指定事件处理时可以在任何元素(包括未在类成员表中列出该特定事件的元素)上侦听和处理路由事件这是通过使用所属类名限定事件名属性来实现的例如在当前所讨论的 StackPanel / Button 示例中父 StackPanel 可以通过在 StackPanel 对象元素上指定属性 ButtonClick并使用处理程序名作为属性值为子元素按钮的 Click 事件注册一个处理程序 x:Name 默认情况下通过处理对象元素而创建的对象实例没有可供您在代码中使用的唯一标识符或固有的对象引用当您在代码中调用构造函数时几乎总是使用构造函数结果为构造的实例设置一个变量以便以后在代码中引用该实例为了对通过标记定义创建的对象进行标准化访问XAML 定义了 x:Name 属性您可以在任何对象元素上设置 x:Name 属性的值在代码隐藏文件中您选择的标识符等效于引用所构造的实例的实例变量在任何方面命名元素都像它们是对象实例一样工作(此名称只是引用该实例)并且代码隐藏文件可以引用该命名元素来处理应用程序内的运行时交互 WPF 框架级 XAML 元素继承 Name 属性 (Property)该属性等效于 XAML 定义的 x:Name 属性 (Attribute)其他某些类也为 x:Name(通常也定义为 Name 属性)提供属性级等效项 一般而言如果您在所选元素的成员表中找不到 Name 属性可以改用 x:Name 下面的示例在 StackPanel 元素上设置 Name然后该 StackPanel 中的 Button 上的处理程序通过由 Name 设置的实例引用 buttonContainer 来引用 StackPanel image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 就像变量一样实例的名称受范围概念的控制因此可以在可预测的某个范围内强制名称唯一定义页面的主要标记表示一个唯一的名称范围而该名称范围的边界就是该页面的根元素但是其他标记源(如样式或样式中的模板)可以在运行时与页面交互这种标记源常常具有其自己的名称范围这些名称范围不一定与页面的名称范围相连接 附加属性和附加事件 XAML 指定了一个语言功能该功能允许在任何元素上指定某些属性或事件而不管要为其设置属性或事件的元素的成员表中是否存在该属性或元素该功能的属性版本称为附加属性事件版本称为附加事件从概念上讲您可以将附加属性和附加事件认为是可以在任何元素/类上设置的全局成员而不管其类层次结构如何 通常通过属性 (Attribute) 语法来使用 XAML 中的附加属性 (Property)在属性 (Attribute) 语法中您可以按照所有者类型属性名 的形式指定附加属性 (Property)表面上这与属性元素用法类似但在这种情况下您指定的所有者类型 始终是一种与要为其设置附加属性的对象元素不同的类型所有者类型 这种类型提供 XAML 处理器获取或设置附加属性值所需要的访问器方法使用附加属性的最常见方案是使子元素能够向其父元素报告属性值 下面的示例演示了 DockPanel::Dock 附加属性DockPanel 类为 DockPanel::Dock 定义访问器因此拥有附加属性DockPanel 类还包括一个逻辑该逻辑迭代其子元素并具体检查每个元素是否具有 DockPanel::Dock 设置值如果找到一个值将在布局过程中使用该值定位子元素使用 DockPanel::Dock 附加属性和这种定位功能事实上是 DockPanel 类的激动人心的一面 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 在 Windows Presentation Foundation (WPF) 中所有附加属性还作为依赖项属性来实现 附加事件使用类似的所有者类型事件名 属性语法形式就像非附加事件一样XAML 中的附加事件的属性值指定在元素上处理事件时调用的处理程序方法的名称 使用附加事件的一种方案适用于可在任何元素(如鼠标按钮)上处理的设备输入事件例如Mouse::MouseDown 就是这样一个附加事件但是大多数 WPF 框架级元素可以使用此事件而无需使用附加事件这是因为基元素类 UIElement 可为 Mouse::MouseDown 附加事件创建一个别名并在 UIElement 成员表中公开该别名(为 MouseDown)因此通常不需要在 XAML 页或 Windows Presentation Foundation (WPF) 应用程序编程中指定附加事件语法例外情况包括您使用的是自定义元素或者使用并非从 UIElement 派生但仍然具有可视化表示形式的对象元素(这些情况很少见)在 WPF 中所有附加事件还作为路由事件来实现ContentElement 也为输入事件公开别名供流程文档模型使用 XAML 页面根元素剖析 下表显示了一个典型的 XAML 页面根元素分解结构并显示了本主题中介绍的根元素的具体属性 image onmousewheel=javascript:return big(this) height= alt= src=http://imgeducitycn/img_///jpg width= onload=javascript:if(thiswidth>)thisstylewidth=; border= twffan=done> 基类和 XAML 基础 XAML 及其架构是一个类集合这些类对应于 CLR 对象以及要在 XAML 中使用的标记元素但是并不是所有的类都能映射到元素抽象类(如 ButtonBase)和某些非抽象基类在 CLR 对象模型中用于继承并且不支持对应的 XAML 标记基类(包括抽象类)对于 XAML 开发仍然很重要因为每个具体的 XAML 元素都从其层次结构中的某个基类继承成员通常这些成员包括可以设置为元素属性 (Attribute) 的属性 (Property)或者可以处理的事件FrameworkElement 是 WPF 在 WPF 框架级的具体 UI 基类设计 UI 时您将使用各种形状面板修饰器或控件类它们全部从 FrameworkElement 派生而来有一个相关的基类 FrameworkContentElement它使用可在 FrameworkElement 中特意镜像 API 的 API支持适合流布局表示形式的面向文档的元素元素级的属性 (Attribute) 和 CLR 对象模型的组合提供了一组通用的属性 (Property)可以在大多数具体的 XAML 元素上设置这些属性 (Property)而不管确切的元素类型及其基础类是什么 XAML 安全性 XAML 是一种直接表示对象实例化和执行的标记语言因此使用 XAML 创建的元素能够像等效的生成代码那样与系统资源进行交互(如网络访问文件系统 IO) WPF 支持 NET 安全框架代码访问安全性 (CAS)这意味着在 Internet 区域中运行的 WPF 内容具有更少的执行权限松散 XAML(由 XAML 查看器在加载时解释的未编译 XAML 的页面)和 XAML 浏览器应用程序 (XBAP) 通常在此 Internet 区域中运行并且使用相同的权限集 但是加载到完全受信任的应用程序中的 XAML 与宿主应用程序具有相同的系统资源访问权限有关更多信息请参见 Windows Presentation Foundation 部分信任安全性 从代码中加载 XAML XAML 可用于定义整个 UI但有时也适合只使用 XAML 定义 UI 的一部分利用此功能可以实现部分自定义在本地存储信息使用 XAML 提供业务对象或者各种可能的方案这些方案的关键是 XamlReader 类及其 Load 方法输入是一个 XAML 文件而输出是一个对象它表示从该标记中创建的对象的整个运行时树然后您可以插入该对象作为应用程序中已存在的另一个对象的属性只要该属性在具有最终显示功能并且将通知执行引擎已在应用程序中添加新内容的内容模型中是一个合适的属性您就可以通过以 XAML 形式加载来轻松地修改正在运行的应用程序的内容请注意通常只在完全受信任的应用程序中使用此功能因为将文件加载到正在运行的应用程序中会带来明显的安全隐患 接下来的内容 本主题简单介绍了 XAML 语法概念和术语 如果您尚未了解这些内容请尝试阅读 Windows Presentation Foundation 入门教程当您真正创建本教程中介绍的标记应用程序时其中的练习将帮助您进一步了解本主题中介绍的许多概念 WPF 使用一个特定的应用程序模型该模型基于 Application 类 生成 WPF 应用程序 (WPF) 为您详细介绍了如何通过命令行以及使用 Microsoft Visual Studio 生成包含 XAML 的应用程序 依赖项属性概述详细介绍了 Windows Presentation Foundation (WPF) 中属性的多样性并介绍了依赖项属性的概念 最后SDK 中还包含一个称为 XAMLPad 的 XAML 编辑工具您可以使用此工具实时体验 XAML |