编辑模型体系结构
设计时实现通过一个称为“编辑模型”的编程接口与运行时控件交互。 正在设计的对象称为“可编辑对象”。 本主题描述 适用于 Visual Studio 的 WPF 设计器中的编辑模型的体系结构和用法。
控件是使用可扩展应用程序标记语言 (XAML) 定义的。 控件 XAML 的更新通过编辑模型,以编程方式实现。
模型、包装和视图
编辑模型包括三个功能子单元:一个模型、一个使模型抽象化的公共包装和一个表示模型的用户界面 (UI) 的视图。 模型和视图是相互独立的,但包装与模型紧密相关。 下图显示了三个子单元的关系。
设计环境使用 ModelItem 类型与基础模型进行通信。 所有更改都针对 ModelItem 包装进行,这些包装影响基础模型。 这样可使模型简单一些。 ModelItem 包装处理复杂的设计器功能,例如事务支持、撤消跟踪以及更改通知。
实例创建
要求在设计图面上创建新对象的任何设计器功能都使用 ModelFactory 类。 设计器中的每个对象都使用 ModelItem 实例包装。 模型项是通过 ModelFactory 创建的。
下面的代码显示一个典型的 ModelFactory 调用。
ModelItem newButton = ModelFactory.CreateItem(_context, typeof(Button));
CreateItem 方法始终返回 ModelItem 的数据类型。 这是 WPF 设计器编辑模型中的所有项的基类型,它表示传递到 CreateItem 方法的类型的包装实例。 CreateItem 方法还需要 WPF 设计器编辑上下文(即上一代码示例中的 _context)的实例,用于定位设计器中的其他服务和依赖项。
对于要放置到设计图面的具有默认初始值设定项的对象而言,通过工厂显式创建项才是必要的。 如果只是将属性设置为值,则无需执行此过程。
始终使用 CreateItem 方法在设计图面上创建新对象。 这是因为许多原始实例都无法解析为模型项。 某值在模型中设置之后,仅应通过模型与该值进行交互。 可随时使用框架重新生成支持模型的实例,这会使已缓存的所有引用失效。
创建选项
有时,您需要自定义对象的创建行为。 例如,数据库连接组件可能不会选择在设计时查询数据库。 您可能希望在第一次创建某个组件时控制对实例的创建。
在这种情况下,将从文本框中拖动某一组件,或通过剪贴板进行粘贴。 您可能希望使用可用默认值预先配置组件。 这些默认值如果未更改,则会序列化到 XAML 中。
您可以使用 CreateOptions 枚举将可选标志集传递到 CreateItem 方法。
工具(例如创建工具)使用 InitializeDefaults 标志来初始化一组预先配置的属性值。 例如,ContentControl 可提供某些默认内容。 这并不会取代使用运行时控件代码来正确指定属性的默认值。
使用此标志设置的值将保存到 XAML 中。
分析代码不应使用此标志,因为用户在设计器中编辑对象时可能已移除这些默认值。
CreateItem 方法将路由对 CreateItem 的调用。 该方法执行若干个步骤,这些步骤在下面的流程图中进行了概述。
将某个项的父级更改为新容器
除创建新项之外,另一个常见设计器任务是将某个项的父级更改为其他父级。 这是通过一个名为 ModelParent 的静态类处理的,该静态类提供了大多数父级设置要求共有的功能。
定位到一个有效的父对象,给定要搜索的层次结构中的坐标偏移量或起始项。
确定某一给定对象是否能作为某一特定类型的父级。
将一个对象的父级更改为另一父级。 此更改还会从对象中移除旧的父级。 通过此移除操作,旧的父级有机会清理驻留在该项中的任何数据(如附加属性)。
ModelParent 类通过定位当前父级对象和建议父级对象的 ParentAdapter 类工作。 如果不存在 ParentAdapter 类,则不能将对象分配给父级。 ParentAdapter 类定义了几种常见的重写。 例如,大多数重写都接受 GestureData 对象作为参数。 此数据类型可在代码处理用户命令时从 WPF 设计器命令机制获取。 它提供通用的上下文信息。
通过 ParentAdapter,容器可以智能移除父级。 例如,如果某一对象的 Canvas 控件父级被更改为 Grid 控件父级,则可自动移除该对象的 Canvas 控件的附加属性。
请参见
参考
Microsoft.Windows.Design.Services