WPF 设计器扩展性体系结构

更新:2007 年 11 月

Visual Studio Windows Presentation Foundation (WPF) 设计器是 WPF 复合控件的可视编辑环境,这些复合控件由 UserControl 类型实现。WPF 设计器基于一个具有可扩展的体系结构的框架,您可以扩展这种框架以创建自己的自定义设计体验。

通过扩展 WPF 设计器对象模型,可以在很大程度上自定义 WPF 内容的设计时外观和行为。例如,可以通过下列方式扩展 WPF 设计器:

  • 利用增强的图形自定义移动并调整标志符号的大小。

  • 向设计图面添加一个标志符号,在鼠标移动时该标志符号可以使所选控件倾斜。

  • 在不同工具之间修改控件的设计时外观和行为。

WPF 设计器 体系结构支持 WPF 的所有表现力。这样便可以创建很多以前不可能拥有的可视化设计体验。

WPF 设计器对象模型

WPF 设计器对象模型是模块化的,这意味着在扩展设计时的时候,只需扩展各项功能所需的元素即可。您不必编写大量支持代码来启用自定义设计功能。 

该对象模型包括五个功能单元,将在下表中对它们进行描述。

功能单元

说明

编辑模型

设计器中对象的编程接口。

功能提供程序

设计器框架中的主扩展性点。

编辑上下文

设计器状态的中央存储区。

工具

用于处理用户输入的工具。

元数据存储区

包含控件的设计时行为以便通过物理方式将设计器逻辑与运行时逻辑分开的存储区。

下面的插图显示了 WPF 设计器对象模型。

高级对象模型

说明:

WPF 设计器支持具有完全扩展性的框架。Expression Blend 只支持属性编辑器、元数据加载和授权。它不支持菜单操作和装饰器。

编辑模型

设计环境通过一个称为编辑模型的编程接口与运行时控件交互。编辑模型包括三个功能子单元:一个模型、一个使模型抽象化的公共包装和一个表示模型的用户界面 (UI) 的视图。

设计环境使用 ModelItem 类型与基础模型进行通信。所有更改都针对 ModelItem 包装进行,这些包装影响基础模型。这样可使模型简单一些。ModelItem 包装处理复杂的设计器功能,例如事务支持、撤消跟踪以及更改通知。

ModelService 类为编辑模型和全局事件通知提供入口点。

ViewService 类将可视化表示形式映射到基础模型项。

设计器需要这两种服务才能发挥作用。DesignerView 类负责处理用户输入并将用户输入传送给命令,该类需要这两种服务才能准确地将用户输入映射回模型。

功能提供程序

可以通过使用 FeatureProviderFeatureConnector<FeatureProviderType> 类来扩展类型的设计时行为。FeatureConnector<FeatureProviderType> 类管理一系列 FeatureProvider 对象。

FeatureProvider 类提供最基本的扩展性点。功能提供程序是一种轻量功能或外接程序,通常它不对设计环境提出更多要求并且在给定上下文中创建和销毁。功能提供程序用于向设计图面中添加新的 UI 位或者用于修改某些基本行为。例如,某个功能提供程序可能会添加更多抓取手柄或者提供一种新的鼠标拖动行为。

若要访问扩展性的最深层,请从 FeatureConnector<FeatureProviderType> 类派生。此类公开一个服务提供程序,派生的功能连接器类可通过该提供程序处理事件并且请求和发布服务。例如,您可能会实现一个功能连接器来提供用于选择的 UI 或对象特定的序列化。

通常,实现功能来扩展现有概念。实现功能连接器来提供新概念。有关更多信息,请参见功能提供程序和功能连接器

编辑上下文

大量状态信息在运行的设计器中累积。例如,设计器状态可能包含以下内容:选择了哪些对象或者在按下鼠标左键时发生的行为。设计器状态存储在一个中央位置,以便在需要时可以找到它。EditingContext 类表示设计器状态的这一中央储存库。

EditingContext 类将状态分为两个类别:数据和行为。数据作为包含上下文项的表存储,行为作为包含服务的表存储。这两个表都根据基于类型的键进行索引并且都可以枚举。

ContextItem 类保留设计器中的单个状态。上下文项是不可变的,但新上下文项可以替换现有上下文项来模拟可变性。

可通过 Services 属性访问服务,该属性返回 ServiceManager 的一个实例;可通过 Items 属性访问上下文项,该属性返回 ContextItemManager 的一个实例。

命令、任务和工具

WPF 设计器工具体系结构包括命令、任务和工具。 

命令是一个表示某一行为的唯一标识符。例如,“剪切”便是一个命令,它表示剪切当前文本并将其添加到剪贴板中。实现“剪切”命令的代码在应用程序之间甚至在一个应用程序内部会有所不同。例如,剪切文本在 Word 文档中的实现与在该相同文档的搜索文本框中的实现是不同的。无论实现如何,“剪切”命令总是相同的。

WPF 设计器通过引入工具命令的概念扩充了 WPF 命令系统。工具命令可实现 ICommand 接口,并与 RoutedCommand 类相似。

“任务”具有命令绑定的集合,允许您添加路由命令。DesignerView 类具有的代码可以使用与工具命令相同的路由策略来查找和执行在任务上定义的路由命令。DesignerView 类启用支持 Copy 等常用 WPF 命令的任务。

“工具”是一个处理用户输入的类。所有用户输入都作为一个或多个输入事件进入设计器。这些输入事件传递到当前活动的工具,后者将它们转换为输入绑定。如果返回的是输入绑定,则执行该绑定内的命令。

工具可以表示设计器的全局模式。例如,如果用户正在选择设计图面上的组件,则可以使用该选择模式,因为当前活动的工具提供可处理选择操作的输入绑定和命令。当用户创建控件的一个新实例时,另一个工具变成活动工具并提供一组不同的命令,这些命令绑定到相同的输入绑定。

元数据存储区

在 WPF 设计器框架中,定义控件的设计时行为的元数据包含在一个单独的程序集内,该程序集被称为“元数据存储区”。在 .NET Framework 3.5 中,元数据存储区在基于代码的属性表内实现,并且外部 XML 文件引用设计器代码和配置文件。不同的工具可以提供具有完全不同的设计器实现的不同元数据存储区。这会使运行时和设计时行为分开,以便您可以独立于控件修订设计器。有关更多信息,请参见元数据存储区

设计器实例的创建

下列步骤演示 WPF 设计器环境如何实例化一个示例设计器类型。此虚构示例演示假设的设计器如何选择设计图面上的一个按钮控件。

  1. 用户调用一个工具定义的操作,该操作请求自定义设计器创建。

  2. 设计环境枚举基于 XML 的功能与类型的关联的列表。

  3. 设计环境通过使用 TypeDescriptor 类向这些类型添加自定义元数据。例如,GrabHandleProvider 可以和所有的 UIElement 类型关联,包括派生类型。

  4. 编辑工厂创建编辑存储区、上下文和功能管理器并填充编辑存储区。

  5. WPF 设计器枚举由编辑存储区公开的所有 UIElement 对象并为每个对象调用 InitializeFeatures 方法。

    1. 假定 Button 元素在此层次结构内声明。

    2. FeatureManager 在按钮上搜索 FeatureAttributeFeatureManager 在类型为 GrabHandleProvider 的按钮上发现了 FeatureAttribute

    3. FeatureManager 继续搜索 GrabHandleProvider 类型并发现了与其关联的 FeatureConnectorAttributeFeatureConnectorAttribute 指定 SelectionConnector。

    4. FeatureManager 确定此宿主尚不存在。FeatureManager 创建 SelectionConnector,并将其添加到活动功能宿主的列表中。

    5. SelectionConnector 对象开始监视设计图面上是否存在所选内容更改。SelectionConnector 对象还获取对装饰器层的引用。

  6. 用户将所选内容更改为按钮,设计时工具引发一个所选内容已更改事件。

  7. SelectionConnector 收到此通知并创建与该所选对象关联的基于所选内容的所有 FeatureProvider 实例,包括 GrabHandleProvider 实例。

  8. SelectionConnector 查询 GrabHandleProvider 以获取一系列装饰器,然后将它们添加到装饰器层。抓取手柄显示在所选按钮周围。

WPF 设计器程序集

WPF 设计器包括若干个程序集,这些程序集分为三个类别:公共类别、私有类别和 Visual Studio 特定的类别。

公共程序集公开可用于向控件添加设计时逻辑的类。

私有程序集和 Visual Studio 特定的程序集定义 WPF 设计器的功能集以及该功能集与 Visual Studio 的交互。下表显示了如何部署 WPF 设计器功能。

程序集

公共 API

说明

Microsoft.VisualStudio.Xaml.dll

Visual Studio SDK 集成逻辑

Microsoft.Windows.Design.Host.dll

宿主设计器的公共 API(特定于 Visual Studio)

Microsoft.Windows.Design.Developer.dll

WPF 设计器实现。只有公共 API 是属性表。

Microsoft.Windows.Design.Core.dll

通过服务和数据底板以及对元数据的操作为任何设计器提供基础。这是 Expression Blend 所支持的唯一程序集。

Microsoft.Windows.Design.Extensibility.dll

通过属性提供扩展性模型。

Microsoft.Windows.Design.Interaction.dll

提供用户输入和显示类。

Microsoft.Windows.Design.Markup.dll

提供可扩展应用程序标记语言 (XAML) 和文档模型机制。

说明:

程序集表示功能边界而不是命名空间边界。通常可以发现跨越一个程序集的命名空间。

WPF 设计器和 Windows 窗体设计器体系结构

WPF 设计器体系结构与 Windows 窗体设计器体系结构差别很大,后者以 IComponent 接口和 System.ComponentModel 命名空间为特征。有关更多信息,请参见比较 Windows 窗体设计器框架与 WPF 设计器框架。 

请参见

概念

功能提供程序和功能连接器

其他资源

设计时开发 Windows 窗体控件

WPF 设计器扩展性