功能提供程序和功能连接器
Windows Presentation Foundation (WPF) 或 Silverlight 应用程序中的任何可设计对象都可以公开任意数目的设计器扩展。 下面的主题讨论功能提供程序的功能,以及功能连接器在提供设计时功能方面的作用。
功能提供程序和功能连接器基础知识
功能提供程序是一个轻型类型,它为对象提供额外的设计时功能。 有些功能提供程序可能仅仅提供有关子组件的信息,不需要代表设计器执行任何操作。 其他功能提供程序可以向对象的设计器上下文菜单添加菜单项、创建用于大小调整或编辑操作的自定义装饰器,或者重新定义对象在设计器上的拖放。
功能提供程序是通过直接从 FeatureProvider 类派生或者从本身也是从 FeatureProvider 派生的类(如 AdornerProvider 和 ContextMenuProvider)派生来实现的。 功能提供程序采用轻型设计,不应尝试在两个实例之间保存状态。
功能连接器为给定对象管理一个或多个功能提供程序。 功能连接器可以通过服务提供程序来发布新服务,还可以侦听设计器事件,如选择的更改。 功能连接器是通过从 FeatureConnector<TFeatureProviderType> 或 PolicyDrivenFeatureConnector<TFeatureProviderType> 类派生新类来实现的。
功能提供程序
功能提供程序旨在成为扩展性的轻型实现。 涉及设计器扩展性时,通常倾向于从现有的功能提供程序类派生,而不是创建新的功能连接器。 功能提供程序不得保存状态,因为它们会创建和销毁多次。
功能提供程序完全是通过功能连接器来管理的,并通过元数据(具体而言是 FeatureAttribute)与对象关联。 功能连接器从此元数据中发现 FeatureProvider 类型。 FeatureManager 类识别发现的每个功能提供程序所需的功能连接器。
常用的功能提供程序实现包括选择装饰器、谓词和属性编辑器。 有关更多信息,请参见演练:创建设计时装饰器。
功能提供程序示例
下图显示了可视化设计器以及可能属于功能提供程序或功能连接器类别的功能类型。 请注意,该图仅仅是一个说明如何实现设计器的某些功能的示例。
下表列出了可以从中派生的功能提供程序。
功能提供程序 |
说明 |
---|---|
向设计器图面添加装饰器。 |
|
添加为主选择内容显示的装饰器。 |
|
定义在上下文菜单中显示的一组菜单项。 |
|
定义为当前选择内容显示的一组菜单项。 |
|
PolicyDrivenFeatureConnector<TFeatureProviderType>.ItemFeatureProvider |
标识属于某个特定项的功能提供程序。 |
向活动工具中添加任务。 |
|
提供当某个类在主选项内容中时选项工具中可用的一组任务。 |
|
捕获用户在设计器中进行的属性更改,并在设计时提供新值。 |
如何在设计时创建功能提供程序
在许多情况下,您不必创建自己的自定义功能连接器。 您可以创建功能连接器,并使用 FeatureConnectorAttribute 将它与某个类直接关联。 FeatureManager 类是用于激活功能提供程序的 WPF 设计器的组件。 在将对象放在设计图面上之后,FeatureManager 会立即检查该对象的元数据。 如果它找到对象的 FeatureConnectorAttribute,将创建关联的功能提供程序。
例如,如果您希望创建一个装饰器,借助它可以直接在设计器图面上编辑自定义控件的标头文本,则应通过从 PrimarySelectionAdornerProvider 派生来实现该装饰器,而此提供程序又是从 FeatureProvider 派生的。 接下来,应当使用 FeatureConnectorAttribute,将自定义装饰器与控件关联。
将功能提供程序与类型关联
设计时工具通过元数据特性将功能提供程序与类型关联。 要实现此关联,必须能够以声明的方式将元数据绑定到实际的运行时对象或实例。 这一绑定在工具级别是必需的,但并非设计时框架的职责。 下图显示了设计时工具如何将功能提供程序附加到各种类型。
在 WPF 设计器体系结构中,存在两种将功能提供程序与类型关联的方法:FeatureAttribute 和 FeatureConnectorAttribute 类型。 FeatureAttribute 类型用在可编辑对象的类型或实例上,并公开一个表示 FeatureProvider 的属性。
FeatureConnectorAttribute 修饰一个 FeatureProvider 类,并指示需要使用哪一类型的功能连接器来承载指定的功能提供程序。 FeatureManager 类在您更改传递给它的对象时创建所需的 FeatureConnector<TFeatureProviderType> 实例。
以一个 WPF 特有的设计器为例。在该设计器中,可编辑对象是 UIElement 类型。 此类工具可能使用一个或多个“抓取控点”来装饰各个项的边界。 这些装饰器以可视方式表示选择内容,并使这些可编辑对象变得可操作。 设计器通过元数据将抓取控点功能与 UIElement 类型的所有对象关联。 下图展示了设计器如何将抓取控点提供程序连接到设计图面上的 UIElement。
如果 UIElement 存在并传递给功能管理器进行分析,将会通过与 UIElement 关联的元数据发现 GrabHandleProvider。 将通过元数据检查 GrabHandleProvider 类型本身或它的基类型,以确定它所需的功能连接器。
功能连接器
功能连接器是此体系结构公开的最低级别的扩展性。 功能连接器是在指定对 EditingContext 的引用的情况下创建的。 功能连接器可以订阅全局服务,并可以添加它们自己的服务。 FeatureConnector<TFeatureProviderType> 抽象类实现 IDisposable 接口,该接口提升简单的清理策略。
功能连接器是按需创建的。 当 FeatureManager 在 FeatureProvider 上发现 FeatureConnectorAttribute 时,会创建指定的 FeatureConnector<TFeatureProviderType>(如果它的类型尚未存在)。 功能连接器只有在被发现时才会创建,而不是让设计器会话在启动时创建一个默认集。 如果 FeatureProvider 存在多个 FeatureConnectorAttribute 类型,将会初始化所有功能连接器。 这样便可以从现有的 FeatureProvider 派生第三方,添加自定义功能连接器,并同时初始化这两组功能。
FeatureConnector<TFeatureProviderType> 类的大多数功能在受保护的 CreateFeatureProviders 方法中实现。 将一个对象传入此方法会使功能连接器在该对象上搜索 FeatureAttribute 类型。 如果找到这些特性,则创建与每个特性相关联的 FeatureProvider 实例,并以列表形式返回这些实例。
FeatureConnector<TFeatureProviderType> 基类为泛型并且使用 FeatureConnector<TFeatureProviderType> 所承载的功能提供程序的类型。 功能提供程序使用 FeatureConnectorAttribute 来指示关联的功能连接器。 FeatureConnector<TFeatureProviderType> 的受保护基类方法(主要是 CreateFeatureProviders 方法)可以将功能提供程序的类型化集合返回到派生的功能连接器,并且派生类不必考虑强制转换和类型安全。
创建自定义功能连接器
当您要侦听设计器事件(如选择)时,必须创建自己的功能连接器。 应通过从 FeatureConnector<TFeatureProviderType> 或 PolicyDrivenFeatureConnector<TFeatureProviderType> 类派生来实现自定义设计器逻辑。
为功能连接器提供了对设计器的全局 EditingContext 的引用,通过此上下文,功能连接器可以访问设计器服务,以及发布自己的自定义服务。 例如,图表控件供应商可能需要发布这样一个服务,该服务使设计器中的自定义类型编辑器可以枚举图表中当前所具有的全部小组件。
在您创建从 FeatureConnector<TFeatureProviderType> 派生的类之后,可以通过向功能提供程序应用 FeatureConnectorAttribute 来将它与功能提供程序关联。 每次创建该功能提供程序的实例时,FeatureManager 都会检查 FeatureConnectorAttribute 的元数据。 如果定义了该特性,但是当前未运行关联的 FeatureConnector<TFeatureProviderType> 的实例,则 FeatureManager 将会创建该实例,并将该功能提供程序的所有将来实例与该 FeatureConnector<TFeatureProviderType> 关联。
有关演示如何实现功能连接器的代码示例,请参见如何:创建自定义功能连接器。