自定义元素创建和移动
可以允许组件拖动到另一个中,从工具箱中或粘贴或移动操作。 可以与目标元素所链接到的移动后的元素,使用您指定的关系。
元素合并指令 (EMD)指定发生的情况,在一个模型元素 合并 到另一个模型元素中。 发生这种情况,当:
用户从在关系图或形状上的工具箱拖动。
用户创建一个元素使用添加菜单在资源管理器或形状隔离舱。
用户从一条泳道项目移动到另一个。
用户粘贴一个元素。
程序代码调用元素合并指令。
尽管创建操作可能看起来与复制操作不同,它们与实际的工作。 当添加元素时,例如从工具箱中,原型从中进行复制。 原型合并到设计与从模型的另一部分进行复制的元素相同。
EMD 的责任是确定应如何将对象的对象或组添加到模型中的特定位置。 具体而言,它决定应实例化的关系链接合并的组添加到模型中。 您还可以自定义它设置属性并创建其他对象。
元素合并指令的角色
,在定义一个嵌入的关系时, EMD 自动生成。 ,当用户将新的子实例添加到父时,此默认 EMD 创建关系的实例。 可以修改这些默认 EMDs,例如通过添加自定义代码。
您还可以将拥有在 DSL 定义的 EMDs,允许用户拖动或粘贴的合并和接收类中的不同组合。
定义元素组合指令
可以添加元素将指令添加到域类、域关系、形状、连接和关系图。 可以添加或找到它们在 DSL 资源管理器中接收的域类下。 接收类中已经在模型元素的域类,,以及新的.rc 或复制的组件将合并。
索引类 是可合并到接收类中的成员元素的字段类。 ,除非您将 适用于子类 为 false,索引类的子类实例将由此 EMD 还合并。
有两个合并指令:
处理将 指令指定新元素应链接到树的关系。
前向 组合 指令将新元素定向到另一个接收的元素,通常父级。
可以将自定义代码来合并指令:
设置 使用自定义接受 添加自己的代码确定是否应将索引组件的特定实例到目标元素。 当用户从工具箱拖动时, “invalid”指针显示代码是否禁止将合并。
例如,因此,只有当进行接收的元素处于特定状态时,您可以允许为合并。
设置 使用自定义合并 将提供自己的代码定义对模型进行更改,当合并完成后。
例如,可以设置该合并的元素的特性使用从其新位置的数据模型的。
备注
如果编写自定义合并代码,则会影响使用此 EMD,仅执行的合并。如果有其他 EMDs 或者,如果具有创建这些对象,而无需使用合并相同的对象,的 EMD 的其他自定义代码,则它们不会受自定义合并代码的影响。
如果要确保,一个新元素或新的关系由自定义代码始终过程,请考虑定义该嵌入关系的 AddRule 和元素中的字段类的 DeleteRule 。有关更多信息,请参见规则在模型内部传播更改。
示例:定义没有自定义代码的 EMD
下面的示例允许用户通过将同时创建元素和连接线从在现有的形状上的工具箱中。 此示例将 EMD 到 DSL 定义。 此修改之前,用户可以拖动工具在关系图上,,但不在现有的形状上。
用户还可以粘贴到其他元素上的元素。
允许用户同时创建元素和连接线
使用 最小的语言 解决方案模板,创建一个新的 DSL。
当您运行此 DSL 时,它使您得以创建形状和连接线在形状之间切换。 不能从工具箱拖动到新 ExampleElement 形状在现有的形状上。
若要允许用户在 ExampleElement 形状上的合并元素中,创建新的 EMD 在 ExampleElement 域类:
在 DSL 资源管理器,展开 域类。 右击 ExampleElement 然后单击 添加新元素合并指令。
确保 DSL 详细信息 窗口处于打开状态,因此,您可以看到新 EMD 的详细信息。 (菜单: 视图、 其他窗口, DSL 详细信息。)
设置在 DSL 详细信息 " 窗口中 索引类 ,定义元素的类可合并在 ExampleElement 对象上。
对于此示例,选择 ExampleElements,这样,用户可以拖动到现有元素上的新元素。
请注意索引类成为 EMD 的名称在 DSL 资源管理器中。
在 通过创建链接处理合并下,添加两个路径:
一个路径与父模型链接新元素。 您需要输入的路径表达式从现有元素进行导航,通过对父模型的嵌入的关系。 最后,它指定在新组件将分配的新链接的效果。 路径如下所示:
ExampleModelHasElements.ExampleModel/!ExampleModel/.Elements
另一个路径与为现有元素链接新元素。 路径表达式指定新元素将分配的引用关系和角色。 此路径如下所示:
ExampleElementReferencesTargets.Sources
可以使用中的路径导航工具创建每个路径:
在 通过创建链接处理将在路径下,单击 add path。
在列表项右侧的下拉箭头。 树视图显示。
展开树的节点窗体要指定的路径。
测试 DSL:
按 F5 重新生成并运行解决方案。
,因为生成的代码从文本模板将更新以符合新的 DSL 定义,重新生成将花费大量时间比正常。
当 Visual Studio 的实验实例启动后,打开 DSL 的模型文件。 创建几个示例元素。
在现有的形状上的 示例元素 工具拖动。
新形状,将出现,并且与现有的形状链接到连接。
复制现有的形状。 选择另一个形状并粘贴。
第一个形状的副本创建。 它具有新名称,并且与第二个形状链接到连接。
以下问题从此程序的通知:
通过创建元素合并指令,可以允许组件任何类接受任何其他的。 EMD 在接收的字段类中创建,并且,接受的域类在 索引类 字段。
通过定义路径,可以指定应该使用哪些链接连接新元素到现有模型。
您指定的链接应包括一个嵌入的关系。
EMD 影响从工具箱中创建并粘贴操作。
使用 ElementOperations.Merge 方法,如果要创建新的组件编写自定义代码,则您可以显式调用 EMD。 这样可确保代码将新元素添加到该模型与其他操作的方式。 有关更多信息,请参见 自定义复制行为。
示例:添加自定义接受代码来 EMD
通过添加自定义代码。 EMD,可以定义更复杂的合并行为。 此简单示例比元素的内置的数字防止用户添加更多到关系图。 该示例修改附带一个嵌入关系的默认 EMD。
编写自定义接受代码限制用户可以添加
使用 最小的语言 解决方案模板,创建一个 DSL。 打开 DSL 定义关系图。
在 DSL 资源管理器中,展开 域类, ExampleModel, 元素合并指令。 选择名为 ExampleElement的元素合并指令。
此 EMD 控件用户如何在模型中创建新 ExampleElement 对象,例如通过从工具箱拖动。
在 DSL 详细信息 窗口中,选择 使用自定义接受。
重新生成解决方案。 ,因为生成的代码与该模型,将更新这将花费大量时间比正常。
编译错误将报告,类似于:“Company.ElementMergeSample.ExampleElement 不包含一个定义为 CanMergeExampleElement…”
必须实现方法 CanMergeExampleElement。
创建新的代码文件。 DSL 项目。 用下面的代码替换其内容并将命名空间添加到项目的命名空间。
using Microsoft.VisualStudio.Modeling; namespace Company.ElementMergeSample // EDIT. { partial class ExampleModel { /// <summary> /// Called whenever an ExampleElement is to be merged into this ExampleModel. /// This happens when the user pastes an ExampleElement /// or drags from the toolbox. /// Determines whether the merge is allowed. /// </summary> /// <param name="rootElement">The root element in the merging EGP.</param> /// <param name="elementGroupPrototype">The EGP that the user wants to merge.</param> /// <returns>True if the merge is allowed</returns> private bool CanMergeExampleElement(ProtoElementBase rootElement, ElementGroupPrototype elementGroupPrototype) { // Allow no more than 4 elements to be added: return this.Elements.Count < 4; } } }
此简单示例限制可合并到父模型元素的数目。 对于更加有趣的情况,方法可以检查任何一个接收的对象的属性和链接。 它还可以检查合并的元素的属性,输入 ElementGroupPrototype。 有关 ElementGroupPrototypes的更多信息,请参见自定义复制行为。 有关并对模型中编写代码的更多信息,请参见 在程序代码中导航和更新模型。
测试 DSL:
按 F5 重新生成解决方案。 当 Visual Studio 的实验实例中打开时,请打开 DSL 的实例。
创建新元素在多种:
从该关系图上的 示例元素 工具拖动。
在 示例模型资源管理器,右击根节点然后单击 添加新元素示例。
复制和粘贴关系图上的元素。
验证是否不能使用这些方法中的任何一个将多于四个元素添加到模型中。 这是因为,它们都使用元素合并指令。
示例:添加自定义合并代码添加到 EMD
在自定义合并代码,可以定义时会发生什么,当用户拖动一个工具或粘贴到元素中。 有两种定义一个自定义合并:
设置 使用自定义合并 并提供必需的代码。 代码替换生成的合并代码。 使用此选项,如果要完全重新定义了该合并。
重写 MergeRelate 方法以及可选 MergeDisconnect 方法。 为此,必须将字段设置类的 生成派生的二进制文件 属性。 代码可以调用基类中生成的合并代码。 使用此选项,如果要执行其他操作,在组合执行后。
通过使用此 EMD,仅执行的这些方法影响合并。 如果要影响该合并的元素可以创建的任何方式,方法是定义该嵌入关系的 AddRule 和在合并的域类的 DeleteRule 。 有关更多信息,请参见规则在模型内部传播更改。
重写 MergeRelate
在 DSL 定义,请确保定义要添加代码的 EMD。 如果需要,可以添加路径,并定义自定义接受代码如前面几节所述。
在 DslDefinition 关系图中,选择为合并接收的类。 它通常是类在一个嵌入关系的源端。
例如,在从最小语言解决方案生成的 DSL,选择 " ExampleModel。
在 属性 窗口中,将 生成派生的二进制文件 到 true。
重新生成解决方案。
检查 Dsl\Generated Files\DomainClasses.cs内容。 搜索名为 MergeRelate 的方法并检查其内容。 这将帮助您编写拥有版本。
在新代码文件,编写接收类中的分部类,并重写 MergeRelate 方法。 确保调用基方法。 例如:
partial class ExampleModel { /// <summary> /// Called when the user drags or pastes an ExampleElement onto the diagram. /// Sets the time of day as the name. /// </summary> /// <param name="sourceElement">Element to be added</param> /// <param name="elementGroup">Elements to be merged</param> protected override void MergeRelate(ModelElement sourceElement, ElementGroup elementGroup) { // Connect the element according to the EMD: base.MergeRelate(sourceElement, elementGroup); // Custom actions: ExampleElement mergingElement = sourceElement as ExampleElement; if (mergingElement != null) { mergingElement.Name = DateTime.Now.ToLongTimeString(); } } }
编写自定义合并代码
在 Dsl\Generated Code\DomainClasses.cs,请检查名为 MergeRelate的方法。 这些方法创建一个新元素和现有模型之间的链接。
另外,请检查名为 MergeDisconnect的方法。 ,当将被删除时,这些方法展开从该模型中的元素。
在 DSL 资源管理器,选择或创建要自定义的元素合并指令。 在 DSL 详细信息 窗口中,将 使用自定义合并。
当将此选项时, 处理合并 和 前向组合 选项被忽略。 使用代码。
重新生成解决方案。 ,因为生成的代码文件从该模型,将更新它将花费大量时间比正常。
错误消息将显示。 双击错误消息会在生成的代码的命令。 这些命令要求为两个方法、 MergeRelateTheDomainClass 和 MergeDisconnectTheDomainClass
编写分部类定义的方法在单独的代码文件。 要检查的示例应及早建议的需要。
自定义合并代码不会影响直接创建对象和关系的代码,因此,它不会影响其他 EMDs。 若要确保,其他实现更改。无论元素如何创建,请考虑编写 AddRule 和 DeleteRule 。 有关更多信息,请参见规则在模型内部传播更改。
重定向合并操作
前向组合指令重定向合并操作的目标。 通常,新的目标是初始目标的嵌入的父级。
例如,在 DSL 用组件图模板创建,端口在元素中。 端口显示为小的形状在组件形状边缘。 用户通过在组件形状上的端口工具创建端口。 但是,在某些情况下,用户错误地拖动到现有的端口上的端口工具,而不是元素,并且,操作将失败。 ,当有多种现有的端口时,这是一个简单的错误。 若要帮助用户避免此讨厌,可以允许端口拖动到现有的端口上,但是,具有事件被重定向到父元素。 操作做法,就好像目标元素的元素。
可以在组件模型解决方案中创建前向组合指令。 如果编译并运行原始解决方案,您应查看用户可以从 工具箱 的任意数量的 输入端 或 输出端口 元素。 元素 元素。 但是,无法拖动端口到现有的端口。 可用指针警报它们此移动未启用。 但是,您可以创建前向组合指令,以便在现有 输入端 会无意删除的端口被转发到 元素 元素。
创建前向组合指令
使用组件模型模板,创建一个 Domain-Specific Language Tools 解决方案。
通过打开 DslDefinition.dsl 显示 DSL 资源管理器 。
在 DSL 资源管理器,展开 域类。
ComponentPort 摘要字段类是 InPort 和 OutPort基类。 右击 ComponentPort 然后单击 添加新元素合并指令。
新的 元素合并指令 节点显示在 元素合并指令 节点下。
选择 元素合并指令 节点并打开 DSL 详细信息 窗口。
在索引课程表,选择 ComponentPort。
选择 将合并到不同的域类。
在路径选择列表中,展开 ComponentPort,展开 ComponentHasPorts,然后选择 元素。
新路径应类似于这个:
ComponentHasPorts.Component/! 元素
保存解决方案,然后单击最右侧的按钮将转换模板在 解决方案资源管理器 工具栏。
生成并运行解决方案。 Visual Studio 新实例出现。
在 解决方案资源管理器,打开 Sample.mydsl。 关系图和 ComponentLanguage 工具箱 显示。
从拖到 工具箱 的 输入端 到另一 **输入端。**接下来,将 OutputPort 到 InputPort 再到另一 OutputPort。
您应当看不到可用指针,因此,您应可以放置在现有一个新的 输入端 。 选择新 输入端 并将它拖到另一个点。 元素。