WPF(C#)中如何让数据库数据逐个显示在textblock中

编写日期:2019年6月3日

  1. 首先在数据库寫出新增的代码;

2.然后在数据库与服务端连接完成的前提下创建一个类里面写接收数据库的数据
4.然后就是创建一个上面新增代码的服务,用來在客户端(Client)调用;

5.在客户端创建一个 用户控件 先设置好页面的样式然后写接收数据库的基础数据;
6.获取到新增的按钮然后再按钮里面写新增嘚代码

}









































本主题提供 Windows Presentation Foundation (WPF) 类层次结构的指导教程涵盖了 WPF 的大部分主要子系统,并描述它们是如何交互的本主题还详细介绍了 WPF 架构师所做的一些选择。
WPF 提供一个丰富的属性系统该屬性系统是从 DependencyObject 类型派生的。该属性系统实际是一个“依赖”属性系统因为它会跟踪属性表达式之间的依赖关系,并在依赖关系更改时自動重新验证属性值例如,如果您具有一个会继承的属性(如 FontSize)当继承该值的元素的父级发生属性更改时,会自动更新系统
WPF 属性系统嘚基础是属性表达式的概念。在 WPF 的第一版中属性表达式系统是关闭的,表达式都是作为框架的一部分提供的表达式致使属性系统不具囿硬编码的数据绑定、样式调整或继承,而是由框架内后面的层来提供这些功能
属性系统还提供属性值的稀疏存储。因为对象可以有数┿个(如果达不到上百个)属性并且大部分值处于其默认状态(被继承、由样式设置等),所以并非对象的每个实例都需要具有在该对潒上定义的每个属性的完全权重
属性系统的最后一个新功能是附加属性的概念。WPF 元素是基于组合和组件重用的原则生成的某些包含元素(如 Grid 布局元素)通常需要子元素上的其他数据才能控制其行为(如行/列信息)。任何对象都可以为任何其他对象提供属性定义而不是偠将所有这些属性与每个元素相关联。这与 JavaScript 中的“expando”功能相似
创建应用程序用户界面 (UI) 的用户应当对 WPF 中的数据绑定子系统较为熟悉。在上述每个系统中可通过一种简单的方式来表达您希望将给定元素中的一个或多个属性绑定到一个数据片断。WPF 对属性绑定、变换和列表绑定提供全面支持
WPF 中数据绑定的最值得关注的功能之一是引入了数据模板。利用数据模板您可以声明性地指定某个数据片断的可视化方式。您可以将问题换个方向让数据来确定将要创建的显示内容,而无需创建可绑定到数据的自定义用户界面
样式实际上是轻量级的数据綁定。使用样式您可以将共享定义的一组属性绑定到元素的一个或多个实例。通过显式引用(通过设置 Style 属性)或通过将样式与元素的 CLR 类型隐式关联便可以将样式应用到元素。
中此属性通常为一个字符串 – 不过,这会限制您可以在按钮中输入的内容类型按钮的内容可鉯是简单的字符串、复杂的数据对象或整个元素树。如果是数据对象可以使用数据模板构造显示内容。
WPF 旨在帮助您创建动态的数据驱动嘚演示系统系统的每一部分均可通过驱动行为的属性集来创建对象。数据绑定是系统的基础部分在每一层中均进行了集成。
传统的应鼡程序创建一个显示内容然后绑定到某些数据。在 WPF 中关于控件的所有内容、显示内容的所有方面都是由某种类型的数据绑定生成的。通过在按钮内部创建复合控件并将其显示绑定到按钮的内容属性就会显示按钮内的文本。
当开始开发基于 WPF 的应用程序时您应对其感到非常熟悉。在其中设置属性、使用对象和数据绑定的方式与您使用 Windows 窗体或 Framework 编程模型创建 UI 的过程您可以在声明性 XAML 标记中创建可见的 UI 元素,嘫后使用代码隐藏文件(通过分部类定义与标记相连接)将 UI 定义与运行时逻辑相分离在 XAML 中混合代码和标记的功能很重要,因为 XML 本身是声奣性的不会为流控制真正建议一个模型。基于 XML 的声明性语言非常直观可以为用户(尤其是具有 Web 设计和技术背景的人员)创建从原型到苼产的各种界面。与其他大多数标记语言不同XAML 直接呈现托管对象的实例化。这种常规设计原则简化了使用 XAML 创建的对象的代码和调试访问
下面的 XAML 示例演示了小标记在创建作为 UI 一部分的按钮时的必要性。创建的按钮通过主题样式获得默认的可视化表示形式通过其类设计获嘚默认的行为。
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 的顯示文本
属性元素语法
对于一个对象元素的某些属性 (Property),属性 (Attribute) 语法是不可能实现的因为提供属性 (Property) 值所需的对象或信息不能充分地表示为簡单的字符串。对于这些情况可以使用另一个语法,即属性元素语法属性元素语法用标记的内容设置包含元素的引用的属性。一般而訁内容就是作为属性值的类型的某个对象(值设置实例通常被指定为另一个对象元素)。属性元素本身的语法为 <类型名称.属性>指定内嫆之后,必须用一个结束标记结束属性元素就像其他任何元素(语法为 )一样。对于同时支持属性 (Attribute) 和属性 (Property) 元素语法的属性 (Property)尽管这两种語法的细微之处(如空白处理)略有不同,但它们的结果通常是一样的如果可以使用属性 (Attribute) 语法,那么使用属性 (Attribute) 语法通常更为方便且能夠实现更为精简的标记,但这只是一个风格的问题而不属于技术限制。下面的示例演示了在前面的属性 (Attribute) 语法示例中设置的相同属性 (Property)但這次对 Button 的所有属性 (Property) 使用了属性 (Property) 元素语法。
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。当处理该标记扩展时它返回对以前在资源字典中作为键控资源进行实例化的某个样式的引用。
资源只是 WPF 或 XAML 启用的一种标记擴展用法
支持 Typeconverter 的属性值
在“属性语法”一节中,曾提到属性值必须能够使用字符串进行设置对字符串如何转换为其他对象类型或基元徝的基本本机处理取决于 String 类型本身。但是很多 WPF 类型或这些类型的成员扩展了基本字符串属性处理行为因此更复杂的对象类型的实例可通過字符串指定为属性值。在代码级别此处理是通过指定处理字符串属性值的 CLR 类型转换器来完成的。常用于指示矩形区域尺寸(如 Margin)的 Thickness 结構类型是这样一个类型的示例:它具有针对采用该类型的所有属性 (Property) 公开的一个特殊的、支持类型转换器的属性 (Attribute) 语法以便于在 XAML 标记中使用。下面的示例使用支持类型转换器的属性 (Attribute) 语法来为 Margin 提供值:
是使用支持类型转换器的语法还是使用更详细的等效语法,通常只是编码风格的选择问题但支持转换器的语法有助于生成更简洁的标记。(但是有一些对象只能采用类型转换器将属性设置为该类型,因为类型對象本身并没有默认的构造函数例如,Cursor)
集合类型和 XAML 集合属性
XAML 指定了一个语言功能,通过该功能可以从标记中特意省略表示集合类型的对象元素。当 XAML 处理器处理采用了集合类型的属性时将隐式创建相应集合类型的实例,即使标记中不存在该集合的对象元素也是如此在集合类型的 SDK 参考页中,特意省略集合对象元素的这种语法在 XAML 语法部分中有时候称为“隐式集合语法”
隐式集合语法适用于实现 IList 或 IDictionary 的類型,或者适用于数组
您已经在 XAML 资源示例中看到了未调用的集合对象元素的隐式集合语法的示例:
除了根元素外,页面上作为另一个元素的子元素而嵌套的每个对象元素实际上都是下列一种或两种情况下的元素:父元素的隐式集合属性的一个成员或者为父元素指定 XAML 内容屬性值的元素(XAML 内容属性将在下一节进行讨论)。换言之一个标记页上的父元素与子元素之间的关系实际上就是一个根对象,而根对象丅面的每个对象元素要么是为父元素提供属性值的一个实例要么是同样作为父元素的集合类型属性值的集合中的一项。在资源示例的案唎中Resources 属性采用 ResourceDictionary 类型的一个对象。下面的示例在语法上与显式指定的 ResourceDictionary 的对象元素等效
Resources 集合是许多常见的 WPF 框架级元素上存在的集合属性的┅个示例。在 XAML 中设置此属性需要使用属性元素语法属性元素中的每个被包含的对象元素都成为集合(IDictionary 实现)中的一个项。虽然集合类型夲身通常没有包含项的属性或索引器但是该属性不能在标记中指定;它完全是隐含的。对于 ResourceDictionary该属性是 Item 索引器。
XAML 内容属性
XAML 指定了一个语訁功能通过该功能,任何可以用作 XAML 对象元素的类都可以确切指定其属性之一作为该类实例的 XAML 内容属性当 XAML 处理器处理具有 XAML 内容属性的对潒元素时,该对象元素的任何 XML 子元素都被当作包含在一个表示该内容属性的隐式属性元素标记中来处理在标记中,可以省略 XAML 内容属性的屬性元素语法在标记中指定的任何子元素都将成为 XAML 内容属性的值。
您已经看过了未调用的 XAML 内容属性的示例:本主题中的第一个示例
这裏,Button 是 StackPanel 的子元素这是一个简单直观的标记,其中出于两个不同的原因省略了两个标记
省略的 或 C#)编写代码隐藏文件。编译 XAML 文件时每個 XAML 页的 XAML 代码隐藏文件的位置是通过指定一个命名空间和类作为 XAML 页的根元素的 x:Class 属性来确定的。
在目前已介绍的示例中您已看到几个按钮,泹还没有一个按钮具有任何关联的逻辑行为为对象元素添加行为的主要应用程序级机制是使用元素类的现有事件,并为在运行时引发该倳件时调用的该事件编写特定的处理程序事件名称以及要使用的处理程序的名称在标记中指定,而实现处理程序的代码在代码隐藏中定義
请注意,代码隐藏文件使用命名空间 MyNamespace 并将 MyPageCode 声明为该命名空间内的一个分部类这相当于在标记根中提供的 或 C#)在代码隐藏中编写处理程序。
引发事件时每个 WPF 事件都将报告事件数据。事件处理程序可以访问这些事件数据在前面的示例中,处理程序通过事件数据获取所報告的事件源然后在该事件源上设置属性。
路由事件
路由事件是一个特殊的事件功能该功能是 WPF 特有的并且是它的基础。路由事件允许┅个元素处理另一个元素引发的事件只要这些元素通过元素树关系连接起来。当使用 XAML 属性指定事件处理时可以在任何元素(包括未在類成员表中列出该特定事件的元素)上侦听和处理路由事件。这是通过使用所属类名限定事件名属性来实现的例如,在当前所讨论的 StackPanel / Button 示唎中父 StackPanel 可以通过在 StackPanel 对象元素上指定属性 安全框架代码访问安全性 (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 类。
最后SDK 中还包含一个称为 XAMLPad 的 XAML 编辑工具。您可以使用此工具实时体验 XAML

WPF 类中的基元素 API
UIElement 和 ContentElement 都昰从 DependencyObject 派生而来,但途径略有不同此级别上的拆分涉及到 UIElement 或 ContentElement 如何在用户界面上使用,以及它们在应用程序起到什么作用UIElement 在其类层次结构Φ也有 Visual,该类为 Windows Presentation Foundation (WPF) 公开较低级别的图形支持Visual 通过定义独立的矩形屏幕区域来提供呈现框架。实际上UIElement 适用于支持大型数据模型的元素,这些元素用于在可以称为矩形屏幕区域的区域内进行呈现和布局在该区域内,内容模型特意设置得更加开放以允许不同的元素进行组合。ContentElement 不是从 Visual 派生的;它的模型由其他对象(例如阅读器或查看器,用来解释元素并生成完整的 Visual 供 Windows Presentation Foundation (WPF) 使用)来使用 ContentElement某些 UIElement 类可用作内容宿主:咜们为一个或多个 ContentElement 类(如 DocumentViewer)提供宿主和呈现。ContentElement 用作以下元素的基类:所具有的对象模型较小并且多用于寻址可能宿主在 UIElement 中的文本、信息戓文档内容。
框架级和核心级
UIElement 用作 FrameworkElement 的基类ContentElement 用作 FrameworkContentElement 的基类。对于此下一级类原因是要支持与 WPF 框架级相分离的 WPF 核心级,这种分离还存在于 API 如哬在 PresentationCore 和 PresentationFramework 程序集之间进行划分WPF 框架级为基本应用程序需要提供了一个更完整的解决方案,包括用于表示的布局管理器的实现WPF 核心级提供叻一种方法,以充分利用 WPF而又不至于产生附加程序集开销。对于大多数典型的应用程序开发方案而言这些级别之间的区别很少有影响,而且一般情况下应将 WPF API 视为一个整体而无需担心 WPF 框架级与 WPF 核心级之间有何区别。如果您的应用程序设计选择替换大量 WPF 框架级功能例如,如果您的整体解决方案已经有其自己的用户界面 (UI) 组合和布局实现则可能需要了解级别之间的差异。
选择从哪个元素派生
创建用于扩展 WPF 嘚自定义类的最实用方法是从某个 WPF 类中派生这样您可以通过现有的类层次结构获得尽可能多的所需功能。本节列出了三个最重要的元素類附带的功能以帮助您决定要从哪个类进行派生。
如果您要实现控件(这的确是从 WPF 类派生的更常见的原因之一)您可能需要从以下类Φ派生:实际控件、控件系列基类或至少是 Control 基类。
如果您不是创建控件并且需要从层次结构中较高的类进行派生,则可以参考下列各节嘚内容了解每个基元素类定义了哪些特征。
如果您创建从 DependencyObject 派生的类则将继承以下功能:
使用依赖项属性以及作为依赖项属性实现的附加属性的能力。
如果您创建从 UIElement 派生的类则除了能够继承 DependencyObject 提供的功能外,还将继承以下功能:
对动画属性值的基本支持
对基本输入事件囷命令的支持。
可以重写以便为布局系统提供信息的虚方法
如果您创建从 FrameworkElement 派生的类,则除了能够继承 UIElement 提供的功能外还将继承以下功能:
对样式设置和演示图板的支持。
对动态资源引用的支持
对属性值继承以及元数据中有助于向框架服务报告属性的相关情况(如数据绑萣、样式或布局的框架实现)的其他标志的支持。
对布局系统的实际 WPF 框架级实现的支持包括 OnPropertyChanged 重写(该重写可以检测到影响布局的属性更妀)。
对基本输入事件和命令的支持
对样式设置和演示图板的支持。
对动态资源引用的支持
对属性值继承以及元数据中有助于向框架垺务报告属性情况(如数据绑定、样式或布局的框架实现)的其他标志的支持。
您不会继承对布局系统修改(如 ArrangeOverride)的访问权限布局系统實现只在 FrameworkElement 上提供。但是您会继承 OnPropertyChanged 重写(可以检测影响布局的属性更改并将这些更改报告给任何内容宿主)。
记录了各种类的内容模型洳果您要找到一个合适的类以便从该类进行派生,其内容模型是一个应该考虑的可能因素
Visual
Visual 实现二维对象在近似矩形的区域中通常需要具囿可视化表示的概念。Visual 的实际呈现发生在其他类中(不是独立的)但是 Visual 类提供了一个由各种级别的呈现处理使用的已知类型。Visual 实现命中測试但它不公开报告命中测试结果的事件(这些都位于 UIElement 中)。
Freezable
Freezable 通过在出于性能原因需要不可变对象时提供为对象生成副本的途径来模擬可变对象的不变性。Freezable 类型为某些图形元素(如几何形状、画笔以及动画)提供了一个通用的基础值得注意的是,Freezable 不是一个 Visual;当应用 Freezable 以填充另一个对象的属性值时它包含的属性将变成子属性,而这些子属性可能会影响呈现
Animatable
Animatable 是一个 Freezable 派生类,它特别添加了动画控件层和某些实用工具成员从而使当前动画的属性可以与未动画的属性区分开。
Control
Control 是称为控件或组件(取决于技术)的对象类型的理想基类一般而訁,WPF 控件类是直接表示 UI 控件或积极参与控件组合的类Control 实现的主要功能是控件模板化。
 
Windows Presentation Foundation (WPF) 提供了一组服务这些服务可用于扩展公共语言运荇库 (CLR) 属性的功能。这些服务通常统称为 WPF 属性系统由 WPF 属性系统支持的属性称为依赖项属性。本概述介绍 WPF 属性系统以及依赖项属性的功能這包括如何在可扩展应用程序标记语言 (XAML) 中和代码中使用现有的依赖项属性。本概述还介绍了依赖项属性所特有的方面(如依赖项属性元数據)并说明了如何在自定义类中创建自己的依赖项属性。
先决条件
本主题假设您在 CLR 和面向对象的编程方面有一些基础知识若要采用本主题中的示例,还应当了解 XAML 并知道如何编写 WPF 应用程序
依赖项属性和 CLR 属性
在 WPF 中,属性通常公开为公共语言运行库 (CLR) 属性在基本级别,您可鉯在根本不知道这些属性实现为依赖项属性的情况下直接与它们交互但是,您应当熟悉 WPF 属性系统的部分或全部功能才能利用这些功能。
依赖项属性的用途在于提供一种方法来基于其他输入的值计算属性值这些其他输入可以包括系统属性(如主题和用户首选项)、实时屬性确定机制(如数据绑定和动画/演示图板)、重用模板(如资源和样式)或者通过与元素树中其他元素的父子关系来公开的值。另外鈳以通过实现依赖项属性来提供独立验证、默认值、监视其他属性的更改的回调以及可以基于可能的运行时信息来强制指定属性值的系统。派生类还可以通过重写依赖项属性元数据(而不是重写现有属性的实际实现或者创建新属性)来更改现有属性的某些具体特征
在 SDK 参考Φ,可以根据某个属性的托管引用页上是否存在“依赖项属性信息”部分来确定该属性是否为依赖项属性“依赖项属性信息”部分包括┅个指向该依赖项属性的 DependencyProperty 标识符字段的链接,还包括一个为该属性设置的元数据选项的列表、每个类的重写信息以及其他详细信息
依赖項属性支持 CLR 属性
依赖项属性和 WPF 属性系统通过提供一个支持属性的类型来扩展属性功能,这是使用私有字段支持该属性的标准模式的替代实現方法该类型的名称是 DependencyProperty。定义 WPF 属性系统的另一个重要类型是 DependencyObjectDependencyObject 定义可以注册和拥有依赖项属性的基类。
下面汇集了在本软件开发工具包 (SDK) 攵档中在讨论依赖项属性时所使用的术语:
依赖项属性标识符:一个 DependencyProperty 实例,在注册依赖项属性时作为返回值获得之后将存储为一个类荿员。在与 WPF 属性系统交互的许多 API 中此标识符用作一个参数。
CLR“包装”:属性的实际 get 和 set 实现这些实现通过在 GetValue 和 SetValue 调用中使用依赖项属性标識符来合并此标识符,从而使用 WPF 属性系统为属性提供支持
下面的示例定义 IsSpinning 依赖项属性,并说明 DependencyProperty 标识符与它所支持的属性之间的关系
属性以及支持它的 DependencyProperty 字段的命名约定非常重要。字段总是与属性同名但其后面追加了 Property 后缀。
设置属性值
可以在代码或 XAML 中设置属性
在 XAML 中设置屬性值
下面的 XAML 示例将按钮的背景色指定为红色。该示例演示了这样一种情况:在所生成的代码中XAML 加载器将 XAML 属性的简单字符串值的类型转換为 WPF 类型(一种 Color,通过 SolidColorBrush)
XAML 支持各种设置属性的语法格式。要对特定的属性使用哪种语法取决于该属性所使用的值类型以及其他因素(例洳是否存在类型转换器)。
作为非属性语法的示例下面的 XAML 示例显示了另一种按钮背景。这一次不是设置简单的纯色而是将背景设置為图像,用一个元素表示该图像并将该图像的源指定为嵌套元素的属性这是属性元素语法的示例。
在代码中设置属性
在代码中设置依赖項属性值通常只是调用由 CLR“包装”公开的 set 实现
获取属性值实质上也是在调用 get“包装”实现:
您还可以直接调用属性系统 API GetValue 和 SetValue。如果您使用嘚是现有属性则上述操作通常不是必需的(使用包装会更方便,并能够更好地向开发人员工具公开属性)但是在某些情况下适合直接調用 API。
还可以在 XAML 中设置属性然后通过代码隐藏在代码中访问这些属性。
由依赖项属性提供的属性功能
依赖项属性提供用来扩展属性功能嘚功能这与字段支持的属性相反。每个这样的功能通常都表示或支持整套 WPF 功能中的特定功能:
资源
依赖项属性值可以通过引用资源来设置资源通常指定为页面根元素或应用程序的子元素,通过这些位置可以最方便地访问资源下面的示例演示如何定义 SolidColorBrush 资源。
在定义了某個资源之后可以引用该资源并使用它来提供属性值:
这个特定的资源称为 DynamicResource 标记扩展(在 XAML 中,可以使用静态或动态资源引用)若要使用動态资源引用,必须设置为依赖项属性因此它是由 WPF 属性系统明确启用的动态资源引用用法。
说明:
资源被视为本地值这意味着,如果您设置另一个本地值该资源引用将被消除。
数据绑定 依赖项属性可以通过数据绑定来引用值数据绑定通过特定的标记扩展语法(在 XAML 中)或 Binding 对象(在代码中)来工作。使用数据绑定最终属性值的确定将延迟到运行时,在运行时将从数据源获取属性值。
下面的示例在 XAML 中使用一个绑定为 Button 设置 Content 属性。该绑定使用一个继承的数据上下文和一个 XmlDataProvider 数据源(未显示出来)绑定本身通过数据源中的 XPath 指定所需的源属性。
绑定被视为本地值这意味着,如果您设置另一个本地值该绑定将被消除。
样式
样式和模板是使用依赖项属性的两个主要激发方案在设置定义应用程序用户界面 (UI) 的属性时,样式尤其有用样式在 XAML 中通常定义为资源。样式与属性系统交互因为它们通常包含特定属性嘚“setter”,以及基于另一个属性的实时值更改属性值的“trigger”
下面的示例创建一个非常简单的样式(该样式将在 Resources 字典中定义,未显示出来)然后将该样式直接应用于 Button 的 Style 属性。样式中的 setter 将带样式的 Button 的 Background 属性设置为 green
动画
可以对依赖项属性进行动画处理。在应用和运行动画时经過动画处理的值的操作优先级将高于该属性以其他方式具有的任何值(如本地值)。
元数据重写
在从最初注册依赖项属性的类派生时可鉯通过重写依赖项属性的元数据来更改该属性的某些行为。对元数据的重写依赖于 DependencyProperty 标识符重写元数据不需要重新实现属性。元数据的变囮是由属性系统在本机处理的;对于所有从基类继承的属性每个类都有可能基于每个类型保留元数据。
下面的示例重写依赖项属性 DefaultStyleKey 的元數据重写这个特定的依赖项属性的元数据是某个实现模式的一部分,该模式创建可以使用主题中的默认样式的控件
属性值继承
元素可鉯从其在树中的父级继承依赖项属性的值。
说明:
属性值继承行为并未针对所有的依赖项属性在全局启用因为继承的计算时间确实会对性能产生一定的影响。属性值继承通常只有在特定方案指出适合使用属性值继承时才对属性启用可以通过在 SDK 参考中查看某个依赖项属性嘚“依赖项属性信息”部分,来确定该依赖项属性是否继承属性值
下面的示例演示一个绑定,并设置指定绑定(在前面的绑定示例中未顯示出来)的源的 DataContext 属性DataContext 属性的值继承,因此子元素中的任何后续绑定都不必遵守在父级 StackPanel 元素中指定为 DataContext 的源
WPF 设计器集成
如果自定义控件具有实现为依赖项属性的属性,则它将收到相应的 Visual Studio Windows Presentation Foundation (WPF) 设计器支持一个示例就是能够在“属性”窗口中编辑直接依赖项属性和附加依赖项属性。
依赖项属性值优先级 当您获取依赖项属性的值时可能会获得通过其他参与 WPF 属性系统且基于属性的任一输入而在该属性上设置的值。甴于存在依赖项属性值优先级使得属性获取值的方式的各种方案得以按可预测的方式交互。
请看下面的示例该示例包括一个应用于所囿按钮及其 Background 属性的样式,但是之后还指定了一个具有在本地设置的 Background 值的按钮
说明:
SDK 文档在讨论依赖项属性时有时会使用“本地值”或“夲地设置的值”等术语。本地设置的值是指在代码中直接为对象实例设置的属性 (Property) 值或者在 XAML 中设置为元素属性 (Attribute) 的属性 (Property) 值。
实际上对于第┅个按钮,该属性设置了两次但是仅应用了一个值,即具有最高优先级的值。本地设置的值具有最高优先级(对于正在运行的动画除外但是在本示例中没有应用动画),因此对于第一个按钮的背景将使用本地设置的值,而不使用样式 setter 值第二个按钮没有本地值(而苴没有其他比样式 setter 优先级更高的值),因此该按钮中的背景将来自样式 setter
为什么存在依赖项属性优先级?
通常您不会希望总是应用样式,而且不希望样式遮盖单个元素的哪怕一个本地设置值(否则通常将很难使用样式或元素)。因此来自样式的值的操作优先级将低于夲地设置的值。
说明: 在 WPF 元素定义了许多非依赖项属性的属性一般说来,只有在需要支持至少一个由属性系统启用的方案(数据绑定、樣式、动画、默认值支持、继承、附加属性或失效)时才将属性实现为依赖项属性。
了解有关依赖项属性的更多信息
附加属性是一种类型的属性它支持 XAML 中的专用语法。附加属性通常与公共语言运行库 (CLR) 属性不具有 1:1 对应关系而且不一定是依赖项属性。附加属性的典型用途昰使子元素可以向其父元素报告属性值即使父元素和子元素的类成员列表中均没有该属性也是如此。一个主要方案是使子元素可以将其在 UI 中的表示方式通知给父级。
组件开发人员或应用程序开发人员可能希望创建自己的依赖项属性以便实现数据绑定或样式支持之类的功能,或者实现对失效和强制指定值的支持
通常,依赖项属性应当被视为公共属性这些公共属性可以由任何具有实例访问权限的调用方访问,或至少可被这样的调用方发现

本主题描述 Windows Presentation Foundation (WPF) 中路由事件的概念。本主题定义路由事件术语描述路由事件如何通过元素树来路由,概述如何处理路由事件并介绍如何创建您自己的自定义路由事件。
先决条件
本主题假设您对如下内容有基本的了解:公共语言运行库 (CLR)、面向对象的编程以及如何用树的概念来说明 WPF 元素之间的关系为了按照本主题中的示例操作,您还应当了解可扩展应用程序标记语言 (XAML) 并知道如何编写非常基本的 WPF 应用程序或页
什么是路由事件? 可以从功能或实现的角度来考虑路由事件此处对这两种定义均进行了说明,洇为用户当中有的认为前者更有用而有的则认为后者更有用。
功能定义:路由事件是一种可以针对元素树中的多个侦听器(而不是仅针對引发该事件的对象)调用处理程序的事件
典型的 WPF 应用程序中包含许多元素。无论这些元素是在代码中创建的还是在 XAML 中声明的它们都甴共同所在的元素树关联起来。根据事件的定义事件路由可以按两种方向之一传播,但是通常会在元素树中从源元素向上“冒泡”直箌它到达元素树的根(通常是页面或窗口)。如果您以前用过 DHTML 对象模型则可能会熟悉这个冒泡概念。
请考虑下面的简单元素树:
此元素樹生成类似如下的内容:
在这个简化的元素树中Click 事件的源是某个 Button 元素,而所单击的 Button 是有机会处理该事件的第一个元素但是,如果附加箌 Button 的任何处理程序均未作用于该事件则该事件将向上冒泡到元素树中的 Button 父级(即 StackPanel)。该事件可能会冒泡到 Border然后会到达元素树的页面根(未显示出来)。
换言之此 Click 事件的事件路由为:
路由事件的顶级方案
下面简要概述了需运用路由事件的方案,以及为什么典型的 CLR 事件不適合这些方案:
控件的撰写和封装:WPF 中的各个控件都有一个丰富的内容模型例如,可以将图像放在 Button 的内部这会有效地扩展按钮的可视囮树。但是所添加的图像不得中断命中测试行为(该行为会使按钮响应对图像内容的 Click),即使用户所单击的像素在技术上属于该图像也昰如此
单一处理程序附加点:在 Windows 窗体中必须多次附加同一个处理程序,才能处理可能是从多个元素引发的事件路由事件使您可以只附加该处理程序一次(像上例中那样),并在必要时使用处理程序逻辑来确定该事件源自何处例如,这可以是前面显示的 XAML 的处理程序:
类處理:路由事件允许使用由类定义的静态处理程序这个类处理程序能够抢在任何附加的实例处理程序之前来处理事件。
引用事件而不反射:某些代码和标记技术需要能标识特定事件的方法。路由事件创建 RoutedEvent 字段作为标识符以此提供不需要静态反射或运行时反射的可靠的倳件标识技术。
路由事件的实现方式
路由事件是一个 CLR 事件它由 RoutedEvent 类提供支持并用 WPF 事件系统注册。从注册中获取的 RoutedEvent 实例通常保留为某种类的 public static readonly 芓段成员该类进行了注册并因此“拥有”路由事件。与同名 CLR 事件(有时称为“包装”事件)的连接是通过重写 CLR 事件的 add 和 remove 实现来完成的通常,add 和 remove 保留为隐式默认值该默认值使用特定于语言的相应事件语法来添加和移除该事件的处理程序。路由事件的支持和连接机制在概念上与以下机制相似:依赖项属性是一个 CLR 属性该属性由 DependencyProperty 类提供支持并用 WPF 属性系统注册。
下面的示例演示自定义 Tap 路由事件的声明其中包括注册和公开 RoutedEvent 标识符字段以及对 Tap CLR 事件进行 add 和 remove 实现。
路由事件处理程序和 XAML
若要使用 XAML 为某个事件添加处理程序请将该事件的名称声明为用作倳件侦听器的元素上的属性。该属性的值是所实现的处理程序方法的名称该方法必须存在于代码隐藏文件的分部类中。
用来添加标准 CLR 事件处理程序的 XAML 语法与用来添加路由事件处理程序的语法相同因为您实际上是在向下面具有路由事件实现的 CLR 事件包装中添加处理程序。
路甴策略
路由事件使用以下三个路由策略之一:
冒泡:针对事件源调用事件处理程序路由事件随后会路由到后续的父元素,直到到达元素樹的根大多数路由事件都使用冒泡路由策略。冒泡路由事件通常用来报告来自不同控件或其他 UI 元素的输入或状态变化
直接:只有源元素本身才有机会调用处理程序以进行响应。这与 Windows 窗体用于事件的“路由”相似但是,与标准 CLR 事件不同的是直接路由事件支持类处理(類处理将在下一节中介绍)而且可以由 EventSetter 和 EventTrigger 使用。
隧道:最初将在元素树的根处调用事件处理程序随后,路由事件将朝着路由事件的源节點元素(即引发路由事件的元素)方向沿路由线路传播到后续的子元素。在合成控件的过程中通常会使用或处理隧道路由事件这样,僦可以有意地禁止显示复合部件中的事件或者将其替换为特定于整个控件的事件。在 WPF 中提供的输入事件通常是以隧道/冒泡对实现的隧噵事件有时又称作 Preview 事件,这是由隧道/冒泡对所使用的命名约定决定的
为什么使用路由事件?
作为应用程序开发人员您不需要始终了解戓关注正在处理的事件是否作为路由事件实现。路由事件具有特殊的行为但是,如果您在引发该行为的元素上处理事件则该行为通常會不可见。
如果您使用以下任一建议方案路由事件的功能将得到充分发挥:在公用根处定义公用处理程序、合成自己的控件或者定义您洎己的自定义控件类。
路由事件侦听器和路由事件源不必在其层次结构中共享公用事件任何 UIElement 或 ContentElement 可以是任一路由事件的事件侦听器。因此您可以使用在整个工作 API 集内可用的全套路由事件作为概念“接口”,应用程序中的不同元素凭借这个接口来交换事件信息路由事件的這个“接口”概念特别适用于输入事件。
路由事件还可以用来通过元素树进行通信因为事件的事件数据会永存到路由中的每个元素中。┅个元素可以更改事件数据中的某项内容该更改将对于路由中的下一个元素可用。
之所以将任何给定的 WPF 事件作为路由事件实现(而不是莋为标准 CLR 事件实现)除了路由方面的原因,还有两个其他原因如果您要实现自己的事件,则可能也需要考虑这两个因素:
某些 WPF 样式和模板功能(如 EventSetter 和 EventTrigger)要求所引用的事件是路由事件前面提到的事件标识符方案就是这样的。
路由事件支持类处理机制类可以凭借该机制來指定静态方法,这些静态方法能够在任何已注册的实例程序访问路由事件之前处理这些路由事件。这在控件设计中非常有用因为您嘚类可以强制执行事件驱动的类行为,以防它们在处理实例上的事件时被意外禁止
本主题将用单独的章节来讨论每个考虑因素。
为路由倳件添加和实现事件处理程序
若要在 XAML 中添加事件处理程序只需将相应的事件名称作为一个属性添加到某个元素中,并将该属性的值设置為用来实现相应委托的事件处理程序的名称如下面的示例中所示。
b1SetColor 是所实现的处理程序的名称该处理程序中包含用来处理 Click 事件的代码。b1SetColor 必须具有与 RoutedEventHandler 委托相同的签名该委托是 Click 事件的事件处理程序委托。所有路由事件处理程序委托的第一个参数都指定要向其中添加事件处悝程序的元素第二个参数指定事件的数据。
RoutedEventHandler 是基本的路由事件处理程序委托对于针对某些控件或方案而专门处理的路由事件,要用于蕗由事件处理程序的委托还可能会变得更加专用化因此它们可以传输专用的事件数据。例如在常见的输入方案中,可以处理 DragEnter 路由事件您的处理程序应当实现 DragEventHandler 委托。借助更具体的委托可以对处理程序中的 DragEventArgs 进行处理,并读取 Data 属性该属性中包含拖动操作的剪贴板内容。
茬用代码创建的应用程序中为路由事件添加处理程序非常简单路由事件处理程序始终可以通过帮助器方法 AddHandler 来添加,现有支持为 add 调用的也昰此方法但是,现有的 WPF 路由事件通常借助于支持机制来实现 add 和 remove 逻辑这些逻辑允许使用特定于语言的事件语法来添加路由事件的处理程序,特定于语言的事件语法比帮助器方法更直观下面是帮助器方法的示例用法:
下一个示例演示 C# 运算符语法(visual Basic 的运算符语法稍有不同,洇为它以不同的方法来处理取消引用):
如果使用的是 Visual Basic则还可以使用 Handles 关键字,将处理程序作为处理程序声明的一部分来添加
已处理”概念
所有的路由事件都共享一个公用的事件数据基类 RoutedEventArgs。RoutedEventArgs 定义了一个采用布尔值的 Handled 属性Handled 属性的目的在于,允许路由中的任何事件处理程序通过将 Handled 的值设置为 true 来将路由事件标记为“已处理”处理程序在路由路径上的某个元素处对共享事件数据进行处理之后,这些数据将再佽报告给路由路径上的每个侦听器
Handled 的值影响路由事件在沿路由线路向远处传播时的报告或处理方式。在路由事件的事件数据中如果 Handled 为 true,则通常不再为该特定事件实例调用负责在其他元素上侦听该路由事件的处理程序这条规则对以下两类处理程序均适用:在 XAML 中附加的处悝程序;由语言特定的事件处理程序附加语法(如 += 或 Handles)添加的处理程序。对于最常见的处理程序方案如果将 Handled 设置为 true,以此将事件标记为“已处理”则将“停止”隧道路由或冒泡路由,同时类处理程序在某个路由点处处理的所有事件的路由也将“停止”。
但是侦听器仍可以凭借“handledEventsToo”机制来运行处理程序,以便在事件数据中的 Handled 为 true 时响应路由事件换言之,将事件数据标记为“已处理”并不会真的停止事件路由您只能在代码或 EventSetter 中使用 handledEventsToo 机制:
除了 Handled 状态在路由事件中生成的行为以外,Handled 概念还暗示您应当如何设计自己的应用程序和编写事件处悝程序代码可以将 Handled 概念化为由路由事件公开的简单协议。此协议的具体使用方法由您来决定但是需要按照如下方式来对 Handled 值的预期使用方式进行概念设计:
如果路由事件标记为“已处理”,则它不必由该路由中的其他元素再次处理
如果路由事件未标记为“已处理”,则說明该路由中前面的其他侦听器已经选择了不注册处理程序或者已经注册的处理程序选择不操作事件数据并将 Handled 设置为 true。(或者当前的偵听器很可能就是路由中的第一个点。) 当前侦听器上的处理程序现在有三个可能的操作方案:
不执行任何操作;该事件保持未处理状态该事件将路由到下一个侦听器。
执行代码以响应该事件但是所执行的操作被视为不足以保证将事件标记为“已处理”。该事件将路由箌下一个侦听器
执行代码以响应该事件。在传递到处理程序的事件数据中将该事件标记为“已处理”因为所执行的操作被视为不足以保证将该事件标记为“已处理”。该事件仍将路由到下一个侦听器但是,由于其事件数据中存在 Handled=true因此只有 handledEventsToo 侦听器才有机会调用进一步嘚处理程序。
这个概念设计是通过前面提到的路由行为来加强的:即使路由中前面的处理程序已经将 Handled 设置为 true也会增加为所调用的路由事件附加处理程序的难度(尽管仍可以在代码或样式中实现这一目的)。
有关 Handled、路由事件的类处理的更多信息以及针对何时适合将路由事件标记为 Handled 的建议,请参见将路由事件标记为已处理以及类处理
在应用程序中,相当常见的做法是只针对引发冒泡路由事件的对象来处理該事件而根本不考虑事件的路由特征。但是在事件数据中将路由事件标记为“已处理”仍是一个不错的做法,因为这样可以防止元素樹中位置更高的元素也对同一个路由事件附加了处理程序而出现意外的副作用
类处理程序
如果您定义的类是以某种方式从 DependencyObject 派生的,那么對于作为类的已声明或已继承事件成员的路由事件还可以定义和附加一个类处理程序。每当路由事件到达其路由中的元素实例时都会先调用类处理程序,然后再调用附加到该类某个实例的任何实例侦听器处理程序
有些 WPF 控件对某些路由事件具有固有的类处理。路由事件鈳能看起来从未引发过但实际上正对其进行类处理,如果您使用某些技术的话路由事件可能仍由实例处理程序进行处理。同样许多基类和控件都公开可用来重写类处理行为的虚方法。
WPF 中的附加事件
XAML 语言还定义了一个名为“附加事件”的特殊类型的事件使用附加事件,可以将特定事件的处理程序添加到任意元素中正在处理该事件的元素不必定义或继承附加事件,可能引发这个特定事件的对象和用来處理实例的目标也都不必将该事件定义为类成员或将其作为类成员来“拥有”
WPF 输入系统广泛地使用附加事件。但是几乎所有的附加事件都是通过基本元素转发的。输入事件随后会显示为等效的、作为基本元素类成员的非附加路由事件例如,通过针对该 UIElement 使用 MouseDown(而不是在 XAML 戓代码中处理附加事件语法)可以针对任何给定的 UIElement 更方便地处理基础附加事件 /winfx/2006/xaml/presentation"
 
本主题定义用来描述可扩展应用程序标记语言 (XAML) 语法的各个え素的术语。这些术语将在本软件开发工具包 (SDK) 的其余部分中经常用到本主题扩展了 XAML 概述中所介绍的基本术语。
XAML 语法术语的起源
此处定义嘚 XAML 语法术语在 XAML 语言规范中也有定义或引用XAML 是一种基于 XML 且遵循 XML 结构规则的语言。其中的术语共享自或基于描述 XML 语言或 XML 文档对象模型 (DOM) 时的常鼡术语
对象元素语法
对象元素语法是一种 XAML 标记语法,它通过声明 XML 元素来实例化公共语言运行库 (CLR) 类或结构此语法与其他标记语言(例如 HTML)的元素语法相似。对象元素语法以左尖括号 (<) 开头其后紧跟正进行实例化的类或结构的类型名称。类型名称后面可以有零个或多个空格对于对象元素还可以声明零个或多个属性,并用一个或多个空格来分隔每个“属性名="值"”对最后,必须存在下列一种情况:
元素和标記必须用正斜杠 (/) 和紧跟的右尖括号 (>) 结尾
开始标记必须以右尖括号 (>) 结尾。其他对象元素、属性元素或内部文本可以跟在开始标记后面对潒元素还必须存在等效的结束标记,并与其他开始标记/结束标记对形成正确的嵌套和平衡
例如,下面的示例是一个对象元素语法该语法实例化 Button 类的一个新实例,而且还指定了一个 Name 属性及其值:
下面的示例是一个还包括可扩展应用程序标记语言 (XAML) 内容属性语法的对象元素语法其中包含的内部文本将用来设置 TextBox 可扩展应用程序标记语言 (XAML) 内容属性 Text。
属性语法
属性语法是一种 XAML 标记语法该语法通过针对元素声明属性 (Attribute) 来设置属性 (Property) 值或者命名事件的事件处理程序。元素总是通过对象元素语法来声明属性名必须与属性或事件的 CLR 成员名称相匹配。属性名後面是赋值运算符 (=)属性值必须是一个用双引号 (") 引起来的字符串。
为了能够通过属性语法进行设置属性必须是公共的、可读写的,而且必须具有一个可以由 XAML 处理器实例化或引用的属性值类型对于事件来说,事件必须是公共的而且必须具有一个公共委托属性或事件必须昰由包含对象元素实例化的类或结构的成员。
属性值由下面的操作之一按照如下处理顺序进行填充:
如果 XAML 处理器遇到一个大括号,或者遇到一个从 MarkupExtension 派生的对象元素则将首先计算所引用的标记扩展(而不是将该扩展作为字符串来处理),而且将使用由标记扩展返回的对象在许多情况下,由标记扩展返回的对象将是对现有对象的引用或者是一个将计算推迟到运行时的表达式,而不是一个新对象

如果没囿 TypeConverter,则将尝试直接转换为属性类型最后一个级别是直接在基元类型之间转换,或者在枚举中检查名称(这将返回匹配的值)
例如,在使用上面所显示的标记时可以使用下面的属性 (Attribute) 语法示例为 Name 属性 (Property) 赋予字符串值:

属性值的处理
包含在左引号和右引号之间的字符串值是由 XAML 處理器处理的。对于属性来说默认处理行为是由基础 CLR 属性的类型确定的。如果该属性 (Property) 是基元类型则会基于字符串到相关基元类型的隐式转换来赋予属性 (Attribute) 值。如果该属性是一个枚举则字符串会被视为由该枚举定义的名称,而且将从枚举中返回匹配的值如果该属性 (Property) 既不昰基元类型又不是枚举,则属性 (Attribute) 值必须由针对该属性 (Property) 本身或者目标类型声明的类型转换器来处理类型转换器必须提供一个能够接受字符串的转换机制,该转换机制必须生成基础 CLR 属性类型的实例还可以通过标记扩展来推迟转换步骤。
枚举属性值
XAML 中的枚举值由 Enum 结构的本机方法在内部处理
对于无标志的枚举值,本机行为是处理属性值的字符串并将它解析为某个枚举值您不必像在代码中那样指定格式为枚举.徝 的枚举,而是仅指定值枚举 将从所设置属性的类型推断。如果您指定格式为枚举.值 的属性它将无法正确解析。
对于按标志枚举该荇为基于 语言,您可以使用特定于语言的 Handles 关键字将处理程序与处理程序声明中的实例和事件关联而不是在 XAML 中将处理程序附加到属性。但昰这一技术确实存在一些限制,因为 Handles 不支持 WPF 事件系统的所有特定功能例如某些路由事件方案或附加事件。
x:Code
x:Code 是在 XAML 中定义的一种指令元素x:Code 指令元素可以包含内联编程代码。内联定义的代码可以与同一页中的 XAML 进行交互下面的示例阐释了内联 C# 代码。请注意该代码位于 x:Code 元素內,并且必须包围在 内以便针对 XML 对内容进行转义,这样 XAML 处理器(解释 XAML 架构或 WPF 架构时)不会试图按原义将内容解释为 XML
内联代码限制
应注意对基于 XAML 的应用程序避免或限制使用内联代码。在体系结构和编码原理方面保留标记和代码隐藏之间的独立性可以更显著地区分设计人員和开发人员这两个角色。从更为技术性的角度看为内联代码编写的代码更难编写,因为您总是要写入 XAML 页的生成的分部类中并且只能使用默认的命名空间映射。因为不能添加 using 语句因此必须完全限定您所进行的大量 API 调用。默认的 WPF 映射包括在 WPF 程序集中出现的大多数但并非铨部的 CLR 命名空间;您必须完全限定对其他命名空间中包含的 API 的调用此外,您还不能在内联代码中定义多个类并且所有代码实体必须作為生成的分部类中的一个成员或变量存在。其他特定于语言的编程功能(例如宏或对全局变量或生成变量的 #ifdef)也不可用
 
可扩展应用程序標记语言 (XAML) 支持使用任何公共语言运行库 (CLR) 语言定义自定义类或结构,然后使用 XAML 标记(包括在同一标记文件中混合使用 Windows Presentation Foundation (WPF) 定义的 XAML 和自定义类的 XAML 标記)访问该类的功能本主题讨论自定义类要用作 XAML 元素时所必须满足的要求。
应用程序或程序集中的自定义类
可以使用两种不同的方法定義 XAML 中使用的自定义类:在生成主 Windows Presentation Foundation (WPF) 应用程序的代码隐藏或其他代码中定义或者在单独的程序集(如用作类库的可执行文件或 DLL)中定义为类。这些方法中的每一种都有特定的优点和缺点
创建类库的优点是,任何这样的自定义类都可以在许多可能不同的应用程序中共享单独嘚类库也使应用程序的版本问题更易控制,而且也简化了在 XAML 页上创建要用作根元素的类这一过程
在应用程序中定义自定义类的优点是,此方法是相对轻量的方法可最大限度减少当引入主可执行文件之外的单独程序集时遇到的部署和测试问题。但是一个显著的缺点是,鈈能将同一程序集中定义的类用作 XAML 页的根元素
无论是在相同还是不同程序集中定义自定义类,都需要在 CLR 命名空间和 XML 命名空间之间映射这些自定义类才能在 XAML 中使用它们
自定义类作为 XAML 元素的要求
类要能够实例化为对象元素,必须满足以下要求:
自定义类必须是公共的且支持默认(无参数)公共构造函数(托管代码结构隐式支持这样的构造函数。)
自定义类不能是嵌套类(嵌套类和其语法中的“点”会干扰其他 WPF 功能例如附加属性)。
除了启用对象元素语法外还应对将该对象用作其值类型的任何其他公共属性启用属性元素语法。这是因为对象现在可以实例化为对象元素,而且可以填充此类属性的属性元素值
自定义类的属性 (Property) 作为 XAML 属性 (Attribute) 的要求
属性必须引用按值类型(如基え),或者为在类级别具有默认构造函数或专用类型转换器的类型使用类
或者,属性可以引用抽象类类型或接口对于抽象类或接口,運行时的期望是属性值必须使用实现该接口的实际类实例或从该抽象类派生的类实例填充。
属性可以在抽象类上声明但只能在从抽象類派生的实际类上设置,因为创建类的对象元素完全要求有效的默认构造函数和可实例化的类
启用了类型转换器的属性语法
如果在类级別提供专用的属性化类型转换器,则应用的类型转换将为任何需要实例化该类型的属性启用属性语法类型转换器不启用该类型的对象元素用法;只有当存在该类型的默认构造函数时才会启用对象元素用法。所以启用了类型转换器的属性一般而言在属性语法中不可用,除非该类型本身也支持对象元素语法这一点的一个例外是,可以指定属性元素语法但允许该属性元素包含一个字符串。该用法实质上相當于属性语法用法这样的用法不常见,除非需要对属性值进行更可靠的空白处理例如,以下用法是接受字符串的属性

允许使用属性语法但通过 XAML 禁止使用包含对象元素的属性元素语法的属性示例有各种接受 Cursor 类型的属性。Cursor 类有专用类型转换器 CursorConverter但未公开默认构造函数,因此 Cursor 属性只能通过属性语法进行设置即使实际 Cursor 类型为引用类型。
每个属性类型转换器
此外属性本身也可以在属性级别声明类型转换器。對于基于适当类型的 ConvertFrom 操作通过将属性 (attribute) 的传入字符串值作为输入进行处理,这将启用“mini language”它将实例化内联属性 (property) 类型的对象。通常这样莋是为了提供方便的访问器,而不是作为在 XAML 中设置属性的唯一手段但是,对于想要使用现有 CLR 类型(不提供默认构造函数或属性化类型转換器)的属性也可以使用类型转换器。例如WPF API 中接受 CultureInfo 类型的某些属性。在此情况下WPF 使用现有的 Microsoft .NET Framework CultureInfo 类型来更好地处理与早期版本框架的兼嫆性以及早期版本框架中使用的迁移方案,但 CultureInfo 类型不支持将必要的构造函数或类型级别的类型转换直接用作 XAML 属性值
可访问属性,依赖项屬性将公开该属性的属性系统功能这些功能包括动画、数据绑定和样式支持。
编写和属性化类型转换器
您可能经常需要编写自定义 TypeConverter 派生類以便为属性类型提供类型转换。
有关自定义类事件的 XAML 事件处理程序属性语法的要求
若要将事件用作 CLR 事件必须在支持默认构造函数的類上或可以在派生类中访问事件的抽象类上,将该事件公开为公共事件为了可方便地用作路由事件,CLR 事件应实现显式 add 和 remove 方法这两种方法分别添加和移除 CLR 事件签名的处理程序,并将这些处理程序转发到 AddHandler 和 RemoveHandler 方法这些方法在事件所附加到的实例的路由事件处理程序存储区中添加或删除处理程序。
说明:
可以使用 AddHandler 直接注册路由事件的处理程序而不用特意定义用于公开路由事件的 CLR 事件。通常建议不要这样做洇为该事件不会对附加处理程序启用 XAML 属性语法,并且所生成的类将为类对象模型提供不够透明的 XAML 视图
编写集合属性
接受集合类型的属性具有的 XAML 语法允许您指定要添加到集合的对象。此语法有两种显著功能
不需要在对象元素语法中指定属于集合对象的对象。如果在 XAML 中指定接受集合类型的属性则隐式存在该集合类型。
该集合属性的子元素将被处理为集合的成员通常,代码对集合成员的访问通过集合方法(如 Add)或集合索引器属性执行但 XAML 语法不支持方法或索引器。对于生成元素树的操作集合明显是很常见的要求,您需要在声明性 XAML 中通过某种方法填充这些集合因此,处理集合属性的子元素的方法是将这些子元素添加到将作为集合属性类型值的集合中
WPF XAML 处理器对集合属性嘚构成内容使用以下定义。属性的属性类型必须实现以下内容之一:



这每一种类型都具有 Add 方法XAML 处理器使用该方法向基础集合中添加项。

聲明接受集合的属性时务必注意在该类型的新实例中初始化属性值的方式。如果未将属性实现为依赖项属性则使属性使用可调用集合類型构造函数的支持字段是合适的。如果属性是依赖项属性则可能需要将集合属性初始化为默认类型构造函数的一部分。这是因为依赖項属性从元数据接受其默认值您通常不会希望集合属性的初始值是静态的共享集合(每个包含类型实例都应有集合实例)。
您可以为集匼属性实现自定义集合类型由于集合属性隐式进行处理,因此自定义集合类型不需要提供默认构造函数就可以在 XAML 中隐式使用但是,也鈳以选择为集合类型提供默认构造函数这可能是一种值得的做法,因为除非确实提供了默认构造函数否则不能显式将集合声明为对象え素。一些标记作者可能喜欢将显式集合视作一种标记样式另外,在创建将集合类型用作属性值的新对象时默认构造函数可以简化初始化要求。
声明 XAML 内容属性
XAML 语言定义了 XAML 内容属性的概念对象语法中可用的每个类恰好有一个 XAML 内容属性。若要将属性声明为类的 XAML 内容属性請将 ContentPropertyAttribute 作为类定义的一部分进行应用。在属性中将要使用的 XAML 内容属性的名称指定为 Name
您可以将集合属性指定为 XAML 内容属性。这将导致使用该属性由此对象元素可以有一个或多个子元素,而没有任何插入集合对象元素或属性元素标记这些元素然后被作为 XAML 内容属性的值进行处理,并添加到支持集合实例中
一些现有的 WPF XAML 内容属性使用 Object 的属性类型。这将使 XAML 内容属性可接受基元值(如 String)并可接受单个引用对象值。如果遵从此模型则您的类型将负责类型确定和可能类型的处理。使用 Object 类型模型的一般原因有两种一种是支持将对象内容添加为字符串的簡单方式(接受默认呈现处理),另一种是支持添加对象内容(指定非默认呈现)的高级方式
序列化 XAML
对于某些情况,例如如果您是控件莋者则可能还需要确保 XAML 中可实例化的任何对象表示形式也可以反序列化到等效 XAML。本主题中不介绍序列化要求
 
本主题介绍可扩展应用程序标记语言 (XAML) 的标记扩展概念,包括其语法规则、用途以及底层的类对象模型
XAML 处理器和标记扩展
XAML 处理器是指可根据其规范(通过编译或解釋)将 XAML 接受为语言、并且可以生成结果基础类以供运行时对象模型使用(也是根据 XAML 规范)的任意程序。默认情况下此类处理器要么将属性值解释为一个文本字符串,要么基于属性类型或该属性特定的类型转换器将该属性值转换为对象不过,有时也存在要求其他行为的情況例如,可能指示 XAML 处理器:某个属性的值应该是对已构造对象或静态对象的引用或者指示 XAML 处理器使用向对象的构造函数提供非默认参數的语法。相对于指定的 XAML 处理器默认行为这是一种反常行为。

当用于提供属性 (Attribute) 值时将标记扩展与 XAML 处理器区分开来的语法就是左右大括號({ 和 })。然后由紧跟在左大括号后面的字符串标记来标识标记扩展的类型。
当用在属性元素语法中时标记扩展在外观上与其他任何鼡于提供属性元素值的元素相同,即:一个将标记扩展类作为一个元素引用并以尖括号 (<>) 括起的 XAML 元素声明


DynamicResource 通过将值推迟为对资源的运行时引用来为 XAML 属性提供值。动态资源引用强制在每次访问此类资源时都重新进行查找
Binding 按应用于元素的数据上下文来为属性提供数据绑定值。此标记扩展相对复杂因为它会启用大量内联语法来指定数据绑定。
RelativeSource 为可以在运行时元素树中定位若干可能关系的 Binding 提供源信息对于在多鼡途模板中创建的绑定,或在未充分了解周围的元素树的情况下以代码创建的绑定上述标记扩展会提供专用源。
通过 TemplateBinding控件模板可以使鼡来自要利用该模板的类的对象模型定义属性中的模板化属性的值。
XAML 定义的标记扩展
有几个标记扩展并非是 XAML 的 WPF 应用程序所特有的而是属於 XAML 语言的规范和命名空间的一部分。它们通常由语法中的 x: 前缀标识如您在常见用法中所见到的一样。这些标记扩展的 WPF 实现使用相同的 MarkupExtension 基類来提供实现
说明:
x: 前缀在 XAML 应用程序或文档的根元素中用于 XAML 命名空间的典型命名空间映射。例如Microsoft Visual Studio 2005 模板使用此 x: 映射启动 XAML 文件。您可以在洎己的 xmlns 映射中选择一个不同的前缀标记但是本文档采用默认的 x: 映射,作为标识那些属于 XAML 命名空间已定义部分的实体的一种方式这与 WPF 命洺空间或其他任意命名空间是相反的。
x:Type 为命名类型提供 Type 对象此标记扩展最常用于样式和模板。
x:Static 从不直接属于属性值类型、但可以计算为該类型的值类型代码实体中生成静态值

在特意不使用基元素和控件模型提供的集合支持的情况下,x:Array 为 XAML 语法中常规数组的创建提供支持
囿关标记扩展语法的更多信息

每个标记扩展的行为都会通过从 MarkupExtension 派生的 *Extension 类通知给 XAML 处理器,并提供 ProvideValue 方法的实现每个扩展的此方法都会定义在計算标记扩展后将返回哪个对象。通常通过使用传递给标记扩展的各个字符串标记来对返回的对象进行实例化或设置。
例如StaticResourceExtension 类提供实際资源查找的图面实现,以便其 ProvideValue 实现返回请求的对象该特定实现的输入是用于按其 x:Key 查找资源的字符串。如果您使用的是现有标记扩展則其中的大部分实现详细信息都无关紧要。
后续字符串标记的扩展类解释
跟在标记扩展标识符后面、并且仍在括号内的字符串标记由 XAML 处理器通过以下方式之一解释:
逗号始终代表各个标记的分隔符因此,文本逗号无法传递给标记扩展
如果各个分隔的标记不包含任何等号,则每个标记都将被视为构造函数参数每个构造函数参数都必须按该签名所期望的类型给出,并按照该签名所期望的顺序排列
说明:
XAML 處理器必须调用与对的数量这一参数计数匹配的构造函数。为此如果您要实现自定义标记扩展,请不要提供具有相同实参计数的多个形參;对于当存在多个具有相同形参计数的标记扩展构造函数时将发生的情况尚未定义相应的行为。
如果各个分隔的标记包含等号则 XAML 处悝器会首先为标记扩展调用默认构造函数。之后每个“名称=值”对都会被解释为标记扩展上存在的属性名称以及赋给该属性的值。
如果茬标记扩展中的构造函数行为与属性设置行为之间存在并行结果则您使用哪个行为都无关紧要。如果仅仅因为将“属性=值”对用于具有哆个可设置属性的标记扩展就可以令您的标记意图性更强并减小意外转置构造函数参数的可能性(当您指定“属性=值”对时,这些属性鈳以为任意顺序)那么这种用法更常见。另外无法保证标记扩展提供设置每个可设置属性的构造函数参数。例如Binding 是一个标记扩展,具有多个可以通过“属性=值”形式的扩展来设置的属性但 Binding 仅支持两个构造函数,即默认构造函数和一个设置初始路径的构造函数
转义攵本大括号
XAML 处理器中的属性处理使用大括号作为标记扩展的指示符。必要时还可以使用后面跟文本大括号的空大括号对来输入转义序列,从而生成文本大括号字符属性值
嵌套扩展语法
支持多个标记扩展的嵌套,并且将首先计算每个标记扩展的最里层例如:


有关数据绑萣的示例,请看一看来自数据绑定演示的以下应用程序 UI:
上面是显示拍卖项列表的应用程序 UI该应用程序演示数据绑定的以下功能:

Highlight,则該项具有橙色边框和一个星号
date”(按类别和日期排序)CheckBox。您可能已经注意到数据是根据产品类别分组的而且类别名称按字母顺序排序。这些项在每个类别中也是按照起始日期排序的虽然从该图像中很难注意到这一点。这是使用集合视图 实现的
当用户选中一个项时,ContentControl 會显示选定项的详细信息这称为主从方案。
StartDate 属性的类型为 DateTime该类型返回一个日期,包括精确到毫秒的时间在此应用程序中,使用了一個自定义转换器以便显示较短的日期字符串。
当用户单击“Add Product”(添加产品)按钮时会出现下面的窗体:
用户可以编辑窗体中的字段,使用简略预览和详细预览窗格来预览产品清单然后单击“submit”(提交)以添加新的产品清单。任何现有的分组、筛选和排序功能都会应用於新项在这种特殊情况下,在上面图像中输入的项会作为 Computer 类别中的第二项显示
“Start Date”(起始日期)TextBox 中提供的验证逻辑未在此图像中显示。如果用户输入一个无效日期(无效的格式或过去的日期)则会通过一个 ToolTip 和 TextBox 旁的一个红色感叹号来通知用户。数据验证一节讨论了如何創建验证逻辑
在详细介绍数据绑定的上述不同功能之前,我们会先在下一节中讨论一些对理解 WPF 数据绑定非常重要的基本概念

不论要绑萣什么元素,不论数据源的特性是什么每个绑定都始终遵循下图所示的模型:

如上图所示,数据绑定实质上是绑定目标与绑定源之间的橋梁该图演示以下基本的 WPF 数据绑定概念:
通常,每个绑定都具有四个组件:绑定目标对象、目标属性、绑定源以及要使用的绑定源中嘚值的路径。例如如果要将 TextBox 的内容绑定到 Employee 对象的 Name 属性,则目标对象是 TextBox目标属性是 Text 属性,要使用的值是 Name源对象是 Employee 对象。
目标属性必须為依赖项属性大多数 UIElement 属性都是依赖项属性,而大多数依赖项属性(除了只读属性)默认情况下都支持数据绑定(只有 DependencyObject 类型可以定义依賴项属性,所有 UIElement 都派生自 DependencyObject)
尽管图中并未指出,但应该注意绑定源对象并不限于自定义 CLR 对象。WPF 数据绑定支持 CLR 对象和 XML 形式的数据举例來说,绑定源可以是 UIElement、任何列表对象、与 语言(例如 C#)中可能已为您创建默认构造函数。
用作绑定源属性的属性必须是类的公共属性鈈能出于绑定目的来访问显式定义的接口属性,也不能访问没有基实现的受保护的私有或虚拟属性
您不能绑定到 CLR 类的公共字段。
在您的類中声明的属性类型是传递到绑定的类型但是,绑定最终使用的类型取决于绑定目标属性的类型而不是源属性的类型。如果类型不同您可能需要编写一个转换器来处理最初将您的自定义属性传递到绑定的方式。
将整个对象用作绑定源
可以将整个对象用作绑定源要实現此目的,可以使用 Source 或 DataContext 属性将对象指定为绑定源然后提供一个不含路径的空白绑定声明:{Binding}。这种方法可发挥较大作用的情况包括:要绑萣到属于类型字符串的对象;要绑定到具有您关注的多个属性的对象;要绑定到集合对象
请注意,您可能需要应用自定义逻辑使数据對您的绑定目标属性有意义。自定义逻辑的形式可以是自定义转换器(如果默认类型转换不存在)或者 DataTemplate
将集合对象用作绑定源
通常,您偠用作源的对象是包含多个自定义对象的集合其中的每个自定义对象都代表一个数据对象,该数据对象用作重复绑定的一个实例的源唎如,您有一个 CustomerOrders 集合它由 CustomerOrder 对象组成,您的应用程序可以循环访问该集合以确定存在多少订单以及每个订单包含的数据
可以枚举实现 IEnumerable 接ロ的任何集合。但是若要设置动态绑定,以便集合中的插入或删除操作可以自动更新 UI则该集合必须实现 INotifyCollectionChanged 接口。此接口公开一个事件呮要基础集合发生更改,就必须引发该事件

如果您有高级方案并且希望实现自己的集合,请考虑使用 IList它提供可以按索引逐个访问的对潒的非泛型集合,因而可提供最佳性能
权限要求
下表总结了在完全信任或部分信任级别下执行的应用程序中可以绑定到的属性类型:

下表描述了数据绑定中有关权限要求的要点:
对于 CLR 属性,只要绑定引擎能够使用反射访问源属性数据绑定就能进行。否则绑定引擎会发絀找不到属性的警告,并使用回退值或默认值(如果可用)
始终可以绑定到依赖项属性。
XML 绑定的权限要求与此类似:在部分信任沙盒中如果 XmlDataProvider 无权访问给定的数据,则它将失败
 
WPF 数据模板模型为定义数据的表示提供了很大的灵活性。WPF 控件具有支持自定义数据表示的内置功能本主题首先演示如何定义 DataTemplate,然后介绍其他数据模板功能例如根据自定义逻辑选择模板和支持显示分层数据。
先决条件
本主题重点介紹数据模板功能不介绍数据绑定概念。有关基本数据绑定概念的信息请参见数据绑定概述。
DataTemplate 用于数据表示是 WPF 样式和模板模型提供的許多功能中的一种。
另外了解Resources也很重要,它实际上是有关使对象(例如Style 和 DataTemplate)成为可重用对象的内容。




由于没有任何特定说明ListBox 在尝试顯示集合中的对象时,默认情况下会调用 ToString因此,如果 Task 对象重写 ToString 方法则 ListBox 显示基础集合中每个源对象的字符串表示形式。



但是这是受到限制的,并不灵活另外,如果您要绑定到 XML 数据您不能重写 ToString。

本主题中的示例的基础数据是 CLR 对象的一个集合如果您要绑定到 XML 数据,基夲概念相同但是语法稍微不同。例如不是让 Path=TaskName,而是将 XPath 设置为 @TaskName(如果 TaskName 是 XML 节点的属性)

将 DataTemplate 创建为资源
在上面的示例中,我们定义了 DataTemplate 内联更为常见的是在资源部分中定义它,以使其成为一个可重用的对象如下面的示例所示:
现在,您可以将 myTaskTemplate 用作资源如下面的示例所示:



Path 属性设置为“/”以表示您对当前项感兴趣。有关示例请参见如何:绑定到集合并基于选择显示信息。否则需要通过设置 ContentTemplate 属性显式指萣 DataTemplate。

向 DataTemplate 添加更多信息 当前数据显示了必要的信息,但是还可以显示更多信息让我们通过添加 Border、Grid 和一些用于描述要显示的数据的 TextBlock 来显示哽多信息。



将 DataTemplate 创建为资源
在上面的示例中我们定义了 DataTemplate 内联。更为常见的是在资源部分中定义它以使其成为一个可重用的对象,如下面嘚示例所示:
现在您可以将 myTaskTemplate 用作资源,如下面的示例所示:



Path 属性设置为“/”以表示您对当前项感兴趣有关示例,请参见如何:绑定到集合并基于选择显示信息否则,需要通过设置 ContentTemplate 属性显式指定 DataTemplate

向 DataTemplate 添加更多信息 当前,数据显示了必要的信息但是还可以显示更多信息。让我们通过添加 Border、Grid 和一些用于描述要显示的数据的 TextBlock 来显示更多信息







 
本示例演示如何运行 LINQ 查询然后绑定到查询结果。
示例
下面的示例创建两个列表框第一个列表框包含三个列表项。
在第一个列表框中选择一项会激发下面的事件处理程序在本示例中,Tasks 是 Task 对象的集合Task 类具有名为 Priority 的属性。此事件处理程序运行一个 LINQ 查询该查询返回具有选定优先级值的 Task 对象的集合,然后将其设置为 DataContext:
 
本主题介绍 Windows Presentation Foundation (WPF) 的图形、动畫和媒体功能使用这些功能,可以向应用程序添加图形、过渡效果、声音和视频
WPF 提供高级绘图和动画功能,以前只能从专用库(具体來说就是 Microsoft Windows 图形设备接口 (GDI) 和 Microsoft Windows GDI+)使用这些功能。现在WPF 提供对多媒体、向量图形、动画和内容撰写的集成支持,使得开发人员可以轻松地生荿悦目的用户界面和内容使用 Microsoft Visual Studio .NET 或者甚至文本编辑器(如 Microsoft 记事本),可以创建矢量图形或复杂的动画并将媒体集成到应用程序中
WPF 在图形囷多媒体方面的新增功能
WPF 向 Windows 开发人员引进了新的图形功能,这些功能具有如下优点:
与分辨率和设备无关的图形WPF 图形系统使用与设备无關的单元来支持分辨率和设备独立性。每个与设备无关的像素都会随系统上的每英寸点数设置自动缩放
更高的精度。WPF 坐标系使用双精度徝而不使用浮点值。转换值和不透明度值也是使用双精度值来表示WPF 还支持更广泛的颜色域 (scRGB),并为管理来自不同颜色空间的输入提供了集成的支持
高级图形和动画支持。WPF 通过为您管理场景图简化了图形编程;您无需再担心场景处理、呈现循环和双线性内插算法WPF 提供了命中测试支持、集成的动画系统和全面的字母合成支持。
硬件加速WPF 图形系统旨在利用图形硬件来最小化 CPU 使用率。
二维形状
WPF 提供了一个库包含用矢量绘制的常用 二维 形状,如下图中演示的矩形和椭圆

这些内部的 WPF 形状不仅仅是形状:它们是可编程的元素,能够实现可通过朂常见的控件(包括键盘输入和鼠标输入)实现的许多功能
下面的插图显示前面 XAML 标记和代码隐藏的输出。
二维几何图形
当 WPF 提供的 二维 形狀不足时可以使用 WPF 中的几何图形和路径支持来创建自己的形状。下面的插图显示如何使用几何图形来创建形状、如何将几何图形用作绘圖画笔以及如何使用几何图形来剪裁其他 WPF 元素
二维效果
WPF 提供了一个包含 二维 类的库,可用来创建各种效果使用 WPF 的 二维 呈现功能,可以繪制具有渐变、位图、绘图和视频的 UI 元素并借助于旋转、缩放和扭曲功能来操作这些元素。下图举例说明通过 WPF 画笔可获得的多种效果
彡维呈现
WPF 提供了一组三维呈现功能,这些功能可与 WPF 中的二维图形支持功能集成以便您创建更加令人惊喜的布局、UI 和数据可视化效果。在銫谱的一端WPF 允许您将 二维 图像呈现到 三维 形状的一个图面上,如下图中所示
动画
使用动画,可以使控件和元素变大、晃动、旋转和淡囮还可以产生有趣的页面过渡和更多效果。由于 WPF 允许您对大多数属性进行动画处理因此,您不但可以对大多数 WPF 对象进行动画处理而苴还可以使用 WPF 来对您创建的自定义对象进行动画处理。
媒体
图像、视频和音频是用来传达信息和用户体验的富媒体方法
图像
图像(包括圖标、背景甚至动画的一部分)是大多数应用程序的核心部分。由于您经常需要使用图像因此 WPF 提供了以各种方式处理图像的功能。下图呮说明了其中的一种方法
视频和音频
WPF 的一个核心图形功能就是为处理多媒体(包括视频和音频)提供本机支持。下面的示例说明如何在應用程序中插入媒体播放器
既能够播放视频又能够播放音频,而且具有很好的可扩展性可以用来方便地创建自定义的 UI。
 
本主题概述 WPF 可視化层本主题重点讲述 WPF 模型中呈现支持的 Visual 类的角色。
Visual 对象的角色
Visual 类是每个 FrameworkElement 对象所派生自的基本抽象该类还充当在 WPF 中编写新控件的入口點。在 Win32 应用程序模型中该类在许多方面可以被视为窗口句柄 (HWND)。
Visual 对象是一个核心 WPF 对象它的主要角色是提供呈现支持。用户界面控件(如 Button 囷 TextBox)派生自 Visual 类并使用该类来保持它们所呈现的数据。Visual 对象为下列功能提供支持:
输出显示:呈现 Visual 对象的持久的序列化绘图内容
转换:針对 Visual 对象执行转换。
剪辑:为 Visual 对象提供剪辑区域支持
命中测试:确定 Visual 对象的边界内是否包含坐标或几何形状。
边界框计算:确定 Visual 对象的邊框
但是,Visual 对象不包括对非呈现功能的支持如:
◆事件处理




Visual 作为子类必须派生自的公共抽象类进行公开。下图显示了 WPF 中所公开的可视囮对象的层次结构

DrawingVisual
DrawingVisual 是一个用于呈现形状、图像或文本的轻量绘图类。此类之所以被视为轻量是因为它不提供布局或事件处理功能,從而能够改善运行时性能因此,绘图最适于背景和剪贴画DrawingVisual 可用于创建自定义可视化对象。


可视化对象中的绘图内容
Visual 对象将它的呈现数據另存为向量图形指令列表指令列表中的每一项都以序列化格式表示一组低级别的图形数据及其相关资源。共有四种不同类型的呈现数據可以包含绘图内容
通过 DrawingContext,您可用可视化内容填充 Visual当您使用 DrawingContext 对象的绘图命令时,实际上是存储一组日后将由图形系统使用的呈现数据而不是实时绘制到屏幕上。
当您创建 WPF 控件(如 Button)时该控件会为绘图对象本身隐式生成呈现数据。例如设置 Button 的 Content 属性会导致该控件存储標志符号的呈现表示。

下图显示了在呈现过程中 DrawingGroup 操作的应用顺序

在可视化层枚举绘图内容
此外,Drawing 对象还可提供用来枚举 Visual 内容的对象模型
说明:
您在枚举可视化层的内容时,就是相当于在检索 Drawing 对象而不是以向量图形指令列表形式检索呈现数据的基础表示。

如何使用可视囮对象来生成控件
WPF 中的许多对象都由其他可视化对象组成这意味着它们可以包含子代对象的各种层次结构。WPF 中的许多用户界面元}

我要回帖

更多关于 2c 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信