自定义工具和工具箱
必须定义元素的工具箱项要允许用户添加到其设计的。 有两种类型的工具:元素工具和连接工具。 在编辑器中生成的设计器,用户选择元素工具形状拖动到关系图,并可以选择连接工具到形状之间的绘图链接。 通常,元素工具允许用户添加域类实例添加到其设计的,因此,连接工具使它们添加域关系实例。
本主题内容:
修改的 " 工具箱 " 选项卡
元素工具
创建组件的组从工具的
连接工具
更改工具箱项的顺序。
工具箱的定义方式。
在 DSL 资源管理器中,展开编辑节点和节点。在下。 通常您将看到类似于的层次结构:
Editor
Toobox Tabs
MyDsl //a tab
Tools
ExampleElement // an element tool
ExampleRelationship // a connection tool
在 DSL 资源管理器中,您可以:
创建新的选项。 选项定义在工具箱的部分标题。
创建新的工具。
复制和粘贴工具。
上移或下移工具在列表中。
删除选项和工具。
重要
若要添加或在 DSL 资源管理器中粘贴到项目中,右击新的节点祖父项。例如,添加工具,右击选项卡而不是 工具 节点。若要添加可选,右击 编辑 节点。
每个工具 工具箱图标 属性引用 16x16 位图文件。 这些文件在 Dsl\Resources 文件夹通常是保留。
元素工具的 类 属性引用特定域类。 默认情况下,工具将创建此类的实例。 但是,可以让编写的代码工具创建不同类型的元素或元素组。
连接工具的 连接生成器 属性引用连接生成器,定义了什么类型的元素工具,可以连接,以及关系它创建在它们之间。 连接生成器定义为 DSL 资源管理器的节点。 连接生成器自动创建,其中要定义的字段关系时,但是,您可以自定义其编写代码。
添加工具到工具箱
,在创建形状类并映射为域类后,通常创建一种元素工具。
,在创建 connect 类和映射为引用关系后,通常创建连接线工具。
在 DSL 资源管理器中,展开 编辑 节点和 " 工具箱 " 选项卡 节点。
右击工具箱选项 " 节点,然后单击 添加新元素工具 或 添加新连接工具。
设置 工具箱图标 属性引用 16x16 位图。
如果要定义新的图标,请创建位图文件在 Dsl\Resources 文件夹的解决方案资源管理器。 文件应具有下列属性值: 生成事件 = 内容; 复制到输出目录 = 不复制。
对于元素工具: 设置工具的 类 属性引用映射到形状的特定域类。
对连接线工具: 设置工具的 连接生成器 特性添加到提供下拉列表中的某个项。 ,在映射加入域关系时,连接生成器自动创建。 如果最近创建的连接,通常会选择该关联的连接生成器。
若要测试 DSL,请按 F5 或 CTRL+F5,然后在 Visual Studio的实验实例中,打开示例设计文件。 新工具应出现在工具箱中。 将其拖到关系图上验证是否创建一个新的元素。
如果工具未出现,请停止的实验 Visual Studio。 在窗口 开始 菜单,请运行 重置 Microsoft Visual Studio 2010 的实验实例。 在 Visual Studio生成 菜单上,单击 重新生成解决方案。 然后再次测试 DSL。
自定义组件工具
默认情况下,工具将创建指定类的一个实例,但是,您可以更改此有两种方法:
,在新元素创建时,请定义元素在其他类中的合并指令,使它们能够接受此类的新实例并使其创建其他的链接。 例如,您可以允许用户拖动到另一个组件上的注释从而创建两者之间的引用链接。
这些自定义项也会影响发生的情况,当用户拖动或粘贴拖放元素。
有关更多信息,请参见 自定义元素创建和移动。
自定义工具编写代码,以便它可以创建元素组。 工具用您可以重写的 ToolboxHelper.cs 的方法中初始化。 有关更多信息,请参见 创建组件的组从工具的。
创建组件的组从工具的
每个元素工具包含它应该创建组件的原型。 默认情况下,每个元素工具创建一个元素,但是,使用一个工具创建相关对象的一组也是可能的。 为此,您可以初始化包含相关项目具有 ElementGroupPrototype 的工具。
下面的示例从中具有类型晶体管的 DSL 中采用。 每个晶体管具有名为 Terminals 的三。 为晶体管的元素工具存储包含四个模型元素和三个关系链接的原型。 当用户拖动到关系图上时的工具,函数原型模型根实例化和链接。
此代码重写在 Dsl\GeneratedCode\ToolboxHelper.cs中定义的方法。
有关自定义使用程序代码模型的更多信息,请参见 在程序代码中导航和更新模型。
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
public partial class CircuitsToolboxHelper
{
/// <summary>
/// Toolbox initialization, called for each element tool on the toolbox.
/// This version deals with each Component subtype separately.
/// </summary>
/// <param name="store"></param>
/// <param name="domainClassId">Identifies the domain class this tool should instantiate.</param>
/// <returns>prototype of the object or group of objects to be created by tool</returns>
protected override ElementGroupPrototype CreateElementToolPrototype(Store store, Guid domainClassId)
{
if (domainClassId == Transistor.DomainClassId)
{
Transistor transistor = new Transistor(store);
transistor.Base = new ComponentTerminal(store);
transistor.Collector = new ComponentTerminal(store);
transistor.Emitter = new ComponentTerminal(store);
transistor.Base.Name = "base";
transistor.Collector.Name = "collector";
transistor.Emitter.Name = "emitter";
// Create an ElementGroup for the Toolbox.
ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
elementGroup.AddGraph(transistor, true);
// AddGraph includes the embedded parts
return elementGroup.CreatePrototype();
}
else
{
return base.CreateElementToolPrototype(store, domainClassId);
} } }
自定义连接工具
通常,那么,当您创建新的 connect 类时,将创建一个元素工具。 或者,可以通过允许两端的类型确定该关系的类型重载一个工具。 例如,您可以定义可创建人员人员关系和 person Town 关系的一个连接工具。
连接工具调用连接生成器。 使用连接生成器指定用户如何链接在编辑器中生成的设计器的元素。 连接生成器指定可链接到的元素和是在它们之间的该链接。
在创建域类之间的某个引用关系,连接生成器自动创建。 ,在映射连接工具时,可以使用此连接生成器。 有关如何创建连接工具的更多信息,请参见 自定义工具和工具箱。
可以修改默认的连接生成器,以便可以处理源和目标类型的不同范围,并创建不同的关系类型。
可以采用连接的生成器编写自定义代码可以指定源和目标类为连接,还定义将进行的连接类型和其他操作与连接的创建。
连接生成器结构
连接生成器包含一个或多个链接连接指令,指定域关系和源和目标元素。 例如,在任务流解决方案模板,可以在 DSL 资源管理器的 CommentReferencesSubjectsBuilder。 此连接生成器包含一个链接连接指令名为 CommentReferencesSubjects,映射到域关系 CommentReferencesSubjects。 此链接连接指令包含指向 Comment 域类的源角色指令和指向 FlowElement 域类的目标角色指令。
使用限制连接的生成器源和目标角色
可以使用连接生成器限制某些类出现在源角色或特定域关系的目标的角色。 例如,您可能有一个到另一个域类的一个字段关系的基本域类,但是,您不能基类的任何派生类具有该关系的相同的效果。 在任务流解决方案,具有四个具体域类 (StartPoint,终结点, MergeBranch 和同步) 直接从抽象域类 FlowElement 继承以及从中间接继承的两个具体域类 (任务和 ObjectInState)。 具有流中引用上 FlowElement 在其源角色和目标角色的字段型类的关系。 但是,终结点域类的实例不应应是流关系的实例的源,也不 StartPoint 类的实例是流关系的实例的目标。 FlowBuilder 连接生成器具有一个链接连接指令指定的命名流的字段类可扮演的角色 (任务、 MergeBranch、 StartPoint 和同步),哪些可以模拟目标角色 (MergeBranch、端点和同步)。
具有多个链接的连接生成器连接指令
您可以添加多个链接连接指令添加到连接生成器。 这可帮助您隐藏某些域模型的复杂用户并使 工具箱 没有获取太混乱。 可以添加链接连接几种不同的域关系的指令对一个连接生成器。 但是,时,它们将执行相同功能时,应合并字段关系。
在任务流解决方案,流连接工具用于绘制流和 ObjectFlow 域关系实例。 FlowBuilder 连接生成器具有,除了流链接外部连接中描述的指令之前,链接连接名为 ObjectFlow 的指令的两个。 这些指令从 ObjectInState 的实例指定 ObjectFlow 关系的实例可以绘制在 ObjectInState 域类的实例之间,或者给它的实例,但是,不在任务的两个实例之间,或者从任务的实例。 ObjectInState 的实例。 但是,流关系的实例可以绘制任务中的两个实例之间。 如果编译和运行任务流解决方案,您可以看到绘制流从 ObjectInState 的实例传递给任务的实例创建 ObjectFlow 的实例,但是,绘制任务的两个实例之间的流创建流的实例。
连接生成器的自定义代码
对于定义连接生成器的自定义项的不同类型的用户界面的四个复选框:
在源或目标角色指令的 自定义接受 复选框
在源或目标角色指令的 自定义联接 复选框
在连接指令的 使用自定义联接 复选框
连接生成器的 是自定义的 属性
您必须提供某些程序代码进行这些自定义项。 若要查看哪些代码必须提供,请检查这些框之一,单击转换所有模板,然后生成解决方案。 错误报告将发生。 双击错误报告查看解释的注释什么代码应添加。
备注
若要将自定义代码,请创建分部类定义中代码文件与可对 GeneratedCode 文件夹中的代码文件。若要避免丢失该工作,您不能编辑生成的代码文件。有关更多信息,请参见 重写和扩展生成的类。
创建自定义连接代码
在每个链接联接指令, 源角色指令 选项从哪种类型定义可以拖动。 同样, 目标指令角色 选项定义内容类型可以拖动。 对于每个类型,可以进一步指定通过设置 自定义接受 标志然后提供额外的代码允许连接 (对于该链接联接指令)。
您还可以自定义发生,则连接时。 例如,您可以自定义该发生拖动到/从特定类的情况下,所有情况一个链接连接指令控制或整个 FlowBuilder 连接生成器。 对于这些选项中的每个元素,则可以将自定义标志在相应级别。 在转换所有模板并尝试生成解决方案时,错误消息处理您在生成的代码的注释。 这些注释标识必须提供。
在组件图中的示例,连接域关系的连接生成器自定义限制可构建在端口之间的连接。 下图演示,可以从 OutPort 元素仅生成连接到 InPort 元素,但是,您可以嵌套在相互嵌套的元素。
来自与 OutPort 一个嵌套元素的连接
因此,可能要指定连接可能来自嵌套的组件。 OutPort。 如下图所示,若要通过此方式指定连接,则将 InPort 类型作为源角色和 OutPort 类型的 使用自定义接受 为 DSL 详细信息 窗口中的目标角色:
链接连接在 DSL 资源管理器的指令
链接连接在 DSL 详细信息 " 窗口的指令
然后必须提供在 ConnectionBuilder 类的方法:
public partial class ConnectionBuilder
{
/// <summary>
/// OK if this component has children
/// </summary>
private static bool CanAcceptInPortAsSource(InPort candidate)
{
return candidate.Component.Children.Count > 0;
}
/// <summary>
/// Only if source is on parent of target.
/// </summary>
private static bool CanAcceptInPortAndInPortAsSourceAndTarget (InPort sourceInPort, InPort targetInPort)
{
return sourceInPort.Component == targetInPort.Component.Parent;
}
// And similar for OutPorts…
有关自定义使用程序代码模型的更多信息,请参见 在程序代码中导航和更新模型。
可以使用类似的代码,例如,阻止用户创建循环通过父子链接。 ,因为用户不会随时,违反它们这些限制视为 “hard 约束。 还可以创建 “soft 验证检查用户通过创建它们不能保存的无效配置临时可以跳过访问。
在定义连接生成器的很好的做法
,才会在概念上相关的,您应定义一个连接生成器创建不同的关系类型。 在任务流示例,则使用相同的生成器创建流在任务之间并在任务和对象之间。 但是,它是 scrum 的使用相同的生成器创建注释和任务之间的关系。
如果定义关系的多种类型的连接生成器,应确保它不能匹配多从相同的类型对源和目标对象。 否则,会导致不可预知的。
使用自定义代码将 “hard 约束,但是,您应考虑用户是否应该可以临时生成无效的连接。 如果它们应,可以修改约束,以便连接进行验证,直到用户尝试保存更改。