创建基于 Windows 窗体的域特定语言
可以使用 Windows 窗体显示域特定语言 (DSL) 模型的状态,而不是使用 DSL 关系图。本主题将逐步完成绑定 Windows 窗体到 DSL,使用 Visual Studio 可视化和 SDK 建模。
DSL 实例显示“Windows 窗体 UI”和模型资源管理器。
创建 Windows 窗体 DSL
“最小 WinForm 设计器” DSL 模板创建可以修改以适合您的需求的最小 DSL。
若要创建最小的 WinForms DSL
创建一个来自**“最小 WinForm 设计器”**模板的 DSL。
在本演练中假设的名称如下所示:
解决方案和 DSL 名称
FarmApp
命名空间
Company.FarmApp
使用模板提供的初始示例的测试:
“转换所有模板”。
生成并运行示例(“CTRL+F5”)。
在 Visual Studio 的实验实例中,在调试项目中打开Sample文件。
注意到在 Windows 窗体控件中显示。
您还可以查看显示在资源管理器中的模型的元素。
在窗体或资源管理器中添加元素,并注意它们显示在另一个 display 中。
在 Visual Studio 的主实例中,请注意有关 DSL 解决方案的下列问题:
DslDefinition.dsl 中不包含任何关系图元素。这是因为,不使用 DSL 关系图查看此 DSL 的实例模型。相反,您将绑定 Windows 窗体到模型,窗体的元素将显示该模型。
除了 Dsl 和 DslPackage 项目外,解决方案包含第三个名为 UI.UI 的项目,项目包含 Windows 窗体控件的定义。DslPackage 依赖 UI,并且, UI 依赖 Dsl。
在 DslPackage 项目的 UI 项目中定义“Windows 窗体”控件,UI\DocView.cs 包含演示该控件的编码。
UI 项目包含绑定到 DSL 的窗体控件的正在运行的示例。但是,当您更改了 DSL 定义,它将不起作用。UI 项目包含:
名为 ModelViewControl 的“Windows 窗体”类。
名为 ModelViewControl 的文件包含 DataBinding.cs 其他的部分的定义。在**“解决方案资源管理器”中查看它的内容,打开文件和选择快捷菜单“查看代码”**。
有关 UI 项目
当更新 DSL 定义文件以定义您自己的 DSL 时,您必须在 UI 项目中更新控件,以显示您的 DSL。不同于Dsl 和 DslPackage项目,示例UI项目不是从DslDefinitionl.dsl中生成的。可以添加 .tt 文件,以生成您所需要的代码(尽管其不是在此演练中转换的)。
正在更新 DSL 定义
以下 DSL 定义用于此演练。
更新 DSL 定义
打开在 DSL 设计器的 DslDefinition.dsl。
删除 ExampleElement
将 ExampleModel 域类重命名为 Farm。
赋予其其他的名为 大小 类型的 Int32,和 IsOrganic 类型的 Boolean的域属性。
说明 如果删除根域类然后创建新的根,则必须重新设置编辑器根类属性。在“DSL 资源管理器”中,选择“编辑器”。然后在“属性”窗口设置“根类”为 Farm。
请使用**“已命名的域类”**工具穿件以下的域类:
Field – 给定名为 Size 的附加域属性。
Animal 在“属性”窗口中,将**“继承修饰符”设置为“抽象”**。
使用**“域类”**工具创建以下类:
Sheep
Goat
请使用**“继承”**工具使“山羊” 和“绵羊”从“动物”中继承。
请使用**“嵌入”**工具嵌入“场”下的 “域”和 “动物”。
建议您整理关系图。若要减少复制的元素数,请使用叶元素的快捷菜单的**“将子树此处”**命令。
解决方案资源管理器工具栏中的**“转换所有模板”**。
生成**“Dsl”**项目。
说明 在此阶段,其他项目在生成时会发生错误。但是,我们需要生成 DSL 项目,这样其程序集可用于数据源配置向导。
更新 UI 项目
现在可以创建用于显示在 DSL 模型中存储的信息的新用户控件。将用户控件与模型相连接的最简单的方法是通过数据绑定。名为**“ModelingBindingSource”**的数据绑定适配器类型转为 DSL 连接到非 VMSDK 接口设计。
定义您的 DSL 模型作为数据源
在**“数据”菜单上,选择“显示数据源”**。
将打开**“数据源”**窗口。
选择**“添加新数据源”。“数据源配置向导”**打开。
选择**“对象”和“下一步”**。
展开 Dsl、Company.FarmApp,然后选择 Farm,它是模型的根类。选择**“完成”**。
在“解决方案资源管理器中”,“UI”项目现在包含Properties\DataSources\Farm.datasource。
您的模型类的属性和关系出现在“数据资源”窗口中。
将模型连接到窗体
在**“UI”**项目中,请删除所有现有的 .cs 文件。
向**“UI”项目中添加名为 FarmControl 的新“用户控制”**文件。
在**“数据源”窗口中,在“场”的下拉菜单上,选择“详细信息”**。
为其他属性保留默认设置。
在设计视图中打开 FarmControl.cs。
将 “数据源”窗口中的**“场”**拖到 FarmControl 上。
控件集显示,每一个集对应一个属性。关系属性不生成控件。
删除 farmBindingNavigator。这在 FarmControl 设计器中还会自动生成,但对此应用程序无用。
使用工具箱将创建两个DataGridView实例,并将它们命名为AnimalGridView和FieldGridView。
说明 可选步骤是将动画和字段从数据源窗口拖动到控件上方。此操作自动创建数据网格和在网格视图和数据源之间的绑定。但是,此绑定不适用于 DSL。因此最好手动创建数据网格和绑定。
如果工具箱不包含 ModelingBindingSource 工具,添加它。在**“数据”** 选项卡的快捷菜单上,选择**“选择项”。在“选择工具箱项”对话框中,从“.NET Framework Tab”选择“.ModelingBindingSource”**。
使用工具箱将创建两个ModelingBindingSource实例,并将它们命名为AnimalBinding和FieldBinding。
设置每一个 ModelingBindingSource 的 DataSource 属性至 farmBindingSource。
设置 DataMember 属性至 Animals 或 Fields。
设置 AnimalGridView 的 DataSource 属性至 AnimalBinding,并设置 FieldGridView 的属性至 FieldBinding。
调整“场”控件的布局满足您的喜好。
ModelingBindingSource 是执行特定于 DSL的若干参数的适配器:
它将包装在 VMSDK 存储事务的更新。
例如,当用户从数据视图栅格中删除行,正则绑定会导致事务异常。
它确保当用户选择行时属性窗口显示相应的模型元素的属性,而不是数据网格行。
数据源和视图之间的连接架构。
完成绑定到 DSL
在**“U”**项目的一个独立的代码文件夹中添加以下代码:
using System.ComponentModel; using Microsoft.VisualStudio.Modeling; using Microsoft.VisualStudio.Modeling.Design; namespace Company.FarmApp { partial class FarmControl { public IContainer Components { get { return components; } } /// <summary>Binds the WinForms data source to the DSL model. /// </summary> /// <param name="nodelRoot">The root element of the model.</param> public void DataBind(ModelElement modelRoot) { WinFormsDataBindingHelper.PreInitializeDataSources(this); this.farmBindingSource.DataSource = modelRoot; WinFormsDataBindingHelper.InitializeDataSources(this); } } }
在**“DslPackage”项目中,请编辑“DslPackage\DocView.tt”**来更新下面的变量定义:
string viewControlTypeName = "FarmControl";
测试 DSL
该 DSL 解决方案现在可以编译并运行,尽管您稍后可能想要添加进一步改进。
要测试的 DSL。
生成并运行解决方案。
在 Visual Studio 的实验实例中,打开**“示例”**文件。
在**“FarmApp 资源管理器”中,打开在“场”根节点上的快捷菜单,并选择“添加新山羊”**。
Goat1 出现在 “动物” 视图。
警告 必须使用在“场”节点,而不是“动物”节点的快捷菜单。
选择 **”场“**根节点并观察其属性。
在窗体视图中,请改变该场的**“名称”或“大小”** 。
在离开窗体中的每个字段时,相应的属性将在“属性”窗口中更改。
增强 DSL
立即提交更新属性
在 FarmControl.cs 设计视图中,选择简单的字段(如名称、大小或 IsOrganic)。
在“属性”窗口中,展开**“DataBindings”,再展开“高级”**.。
在**“格式设置和高级绑定”对话中,在“数据源更新模式”下,选择OnPropertyChanged**。
生成并运行解决方案。
验证更改字段的内容时,立刻更改场模型的相应属性。
提供添加按钮
在 FarmControl.cs 设计视图中,请使用工具箱来创建窗体上的按钮。
编辑按钮的名称和文本,如 New Sheep。
在按钮后打开该代码(例如通过双击它)。
编辑如下:
private void NewSheepButton_Click(object sender, EventArgs e) { using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep")) { elementOperations.MergeElementGroup(farm, new ElementGroup(new Sheep(farm.Partition))); t.Commit(); } } // The following code is shared with other add buttons: private ElementOperations operationsCache = null; private ElementOperations elementOperations { get { if (operationsCache == null) { operationsCache = new ElementOperations(farm.Store, farm.Partition); } return operationsCache; } } private Farm farm { get { return this.farmBindingSource.DataSource as Farm; } }
您将还需要插入以下指令:
using Microsoft.VisualStudio.Modeling;
为“山羊”和“字段”添加类似的按钮。
生成并运行解决方案。
验证新按钮添加项。新项目应出现在 FarmApp “资源管理器”和适当的数据网格视图中。
您应当能够在数据网格视图中编辑元素的名称。您可以从所在位置将其删除。
有关要添加到元素的代码
对于新元素按钮,以下替换代码略微简单。
private void NewSheepButton_Click(object sender, EventArgs e)
{
using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep"))
{
farm.Animals.Add(new Sheep(farm.Partition)); ;
t.Commit();
}
}
但是,此代码不为新项设置默认名称。它不运行您在 DSL 的 “元素合并指令” 可能已定义的任何自定义的合并,因此,它不运行可能已定义的任何自定义合并代码。
因此我们建议您使用 ElementOperations 来创建新元素。有关更多信息,请参见自定义元素创建和移动。