使用域特定语言修改标准的菜单命令
可修改某些在 DSL 中自动定义的标准命令的行为。 例如,可以修改“Cut”,以便排除敏感信息。 若要实现此目的,请重写命令集类中的方法。 这些类定义在 DslPackage 项目的 CommandSet.cs 文件中,并派生自 CommandSet。
注意
如果要创建自己的菜单命令,请参阅如何:向快捷菜单添加命令。
可以修改哪些命令?
发现可以修改的命令
在
DslPackage
项目中,打开GeneratedCode\CommandSet.cs
。 可在“解决方案资源管理器”中找到作为CommandSet.tt
补充文件的这个 C# 文件。在此文件中查找其名称以“
CommandSet
”结尾的类,例如Language1CommandSet
和Language1ClipboardCommandSet
。在每个命令集类中,键入“
override
”,后跟一个空格。 IntelliSense 将显示可重写方法的列表。 每个命令具有一对其名称以“ProcessOnStatus
”和“ProcessOnMenu
”开头的方法。记录哪些命令集类包含你想要修改的命令。
关闭该文件,无需保存编辑。
注意
通常,不应编辑已生成的文件。 任何编辑都将在下次生成文件时丢失。
扩展相应的命令集类
创建包含命令集类的分部声明的新文件。
扩展命令集类
在“解决方案资源管理器”中,在 DslPackage 项目中打开 GeneratedCode 文件夹,然后在 CommandSet.tt 下进行查找并打开其生成的文件 CommandSet.cs。 注意在此处定义的第一个类的命名空间和名称。 例如,你可能看到:
namespace Company.Language1
{ ... internal partial class Language1CommandSet : ...
在“DslPackage”中,创建名为“Custom Code”的文件夹。 在此文件夹中,创建名为
CommandSet.cs
的新的类文件。在该新文件中,编写具有与生成的分部类相同的命名空间和名称的分部声明。 例如:
using System; using System.Collections.Generic; using System.ComponentModel.Design; namespace Company.Language1 /* Make sure this is correct */ { internal partial class Language1CommandSet { ...
注意
如果已使用类文件模板创建该新文件,则必须同时更正命名空间和类名。
重写命令方法
大多数命令都有两个关联的方法:名称为 ProcessOnStatus
... 的方法确定是否应显示和启用该命令。 它将在每当用户右键单击关系图时调用,并应快速执行且不做任何更改。 ProcessOnMenu
... 将在用户单击命令时调用,并且应执行该命令的函数。 你可能想要重写其中一个方法,或两者都进行重写。
更改命令何时显示在菜单上
重写 ProcessOnStatus... 方法。 此方法应设置其参数 MenuCommand 的“可见”和“已启用”属性。 通常,命令查看 this.CurrentSelection 来确定命令是否应用到选定的元素,还可能查看其属性来确定命令是否可以应用到其当前状态中。
一般原则是,“可见”属性应由选定了哪些什么元素来确定。 “已启用”属性(确定命令在菜单上是显示为黑色还是灰色)应取决于选择的当前状态。
以下示例将在用户已选择多个形状时禁用“删除”菜单项。
注意
此方法不影响命令通过击键是否可用。 例如,禁用“删除”菜单项不会阻止通过 Delete 键来调用命令。
/// <summary>
/// Called when user right-clicks on the diagram or clicks the Edit menu.
/// </summary>
/// <param name="command">Set Visible and Enabled properties.</param>
protected override void ProcessOnStatusDeleteCommand (MenuCommand command)
{
// Default settings from the base method.
base.ProcessOnStatusDeleteCommand(command);
if (this.CurrentSelection.Count > 1)
{
// If user has selected more than one item, Delete is greyed out.
command.Enabled = false;
}
}
最佳做法是先调用基方法,以处理所有你无需考虑的用例和设置。
ProcessOnStatus 方法不应在“存储”中创建、删除或更新元素。
更改命令的行为
重写 ProcessOnMenu... 方法。 以下示例将阻止用户一次删除多个元素,即使使用 Delete 键也是如此。
/// <summary>
/// Called when user presses Delete key
/// or clicks the Delete command on a menu.
/// </summary>
protected override void ProcessOnMenuDeleteCommand()
{
// Allow users to delete only one thing at a time.
if (this.CurrentSelection.Count <= 1)
{
base.ProcessOnMenuDeleteCommand();
}
}
如果你的代码将对“存储”进行更改(例如创建、删除或更新元素或链接),则必须在事务内进行这些更改。 有关详细信息,请参阅如何创建和更新模型元素。
编写方法的代码
以下片段通常在这些方法内十分有用:
this.CurrentSelection
。 用户右键单击的形状始终包含在此形状和连接符列表中。 如果用户单击关系图的空白部分,则“关系图”是该列表中的唯一成员。如果用户单击了关系图的空白部分,则为
this.IsDiagramSelected()
-true
。this.IsCurrentDiagramEmpty()
this.IsSingleSelection()
- 用户未选择多个形状this.SingleSelection
- 用户右键单击的形状或关系图shape.ModelElement as MyLanguageElement
- 由形状表示的模型元素。
有关如何在元素之间进行导航以及如何创建对象和链接的详细信息,请参阅在程序代码中导航和更新模型。