好吧,自从我几天前问this question以来,我的DSL已经取得了显着进展。
一旦我重构了我的代码,我就会发布自己的答案,但就目前而言,我还有其他问题。
我从DSL创建的模型中动态生成子图,将这些图保存为图像,然后生成嵌入了这些图像的Word文档。到目前为止,非常好。
但是我的形状有隔间(例如,服务合同上的操作 - 你能猜出它是什么吗?),会显示隔间标题,但没有任何项目。
如果我检查我的形状对象,它有一个嵌套的子元素 - 一个ElementListCompartment,它反过来有一些我期望显示的项目。 ElementListCompartment.IsExpanded属性设置为true(并且隔离专区标题上有一个“折叠”图标)但是哪里,哪里,我的项目?
使用
将形状添加到图表中parentShape.FixupChildShapes(modelElement);
那么,有人能以我的快乐方式指导我吗?
答案 0 :(得分:2)
我最近遇到了一个相关问题,并设法让它发挥作用,所以这就是故事。
我正在实施的任务是加载和显示由ActiveWriter的DSL包生成的域模型和关联图。
以下是我实现所需功能的方法(以下所有方法都属于我创建的Form1类):
private Store LoadStore()
{
var store = new Store();
store.LoadDomainModels(typeof(CoreDesignSurfaceDomainModel), typeof(ActiveWriterDomainModel));
return store;
}
private void LoadDiagram(Store store)
{
using (var tx = store.TransactionManager.BeginTransaction("tx", true))
{
var validator = new ValidationController();
var deserializer = ActiveWriterSerializationHelper.Instance;
deserializer.LoadModelAndDiagram(store,
@"..\..\ActiveWriter1.actiw", @"..\..\ActiveWriter1.actiw.diagram", null, validator);
tx.Commit();
}
}
private DiagramView CreateDiagramView()
{
var store = LoadStore();
LoadDiagram(store);
using (var tx = store.TransactionManager.BeginTransaction("tx2", true))
{
var dir = store.DefaultPartition.ElementDirectory;
var diag = dir.FindElements<ActiveRecordMapping>().SingleOrDefault();
var view = new DiagramView(){Diagram = diag};
diag.Associate(view);
tx.Commit();
view.Dock = DockStyle.Fill;
return view;
}
}
protected override void OnLoad(EventArgs e)
{
var view = CreateDiagramView();
this.Controls.Add(view);
}
这个东西大部分工作都很好:它正确地从用Visual Studio创建的文件加载图表,在我的自定义窗体中绘制图表,支持滚动画布甚至允许我在这里拖动形状。然而,有一件事让我烦恼 - 隔间是空的并且有默认名称,即“隔间”。
谷歌没有任何帮助,所以我不得不自己挖掘。这不是很容易,但在Reflector的帮助下,花了几个小时后我设法使这个场景按预期工作!问题如下。令我惊讶的是,DSL库在添加到图表后不会立即正确绘制某些图表元素。有时,只绘制某些形状的存根(因为它显示在第一张图片中)。因此,有时我们需要手动要求库重绘图形。
此功能可以使用所谓的“规则”来实现,这些规则实际上是由某些图事件触发的事件处理程序。基本上我们要做的是将某个处理程序附加到图中添加元素的事件并确保形状初始化。
幸运的是,我们甚至不必编写任何代码,因为DSL设计器会自动生成修复规则和将这些规则附加到图表中的实用程序方法(请参阅下面的EnableDiagramRules)。我们所要做的就是在创建商店之后立即调用此方法(在加载模型和图表之前)。
private Store LoadStore()
{
var store = new Store();
store.LoadDomainModels(typeof(CoreDesignSurfaceDomainModel), typeof(ActiveWriterDomainModel));
ActiveWriterDomainModel.EnableDiagramRules(store);
return store;
}
/// <summary>
/// Enables rules in this domain model related to diagram fixup for the given store.
/// If diagram data will be loaded into the store, this method should be called first to ensure
/// that the diagram behaves properly.
/// </summary>
public static void EnableDiagramRules(DslModeling::Store store)
{
if(store == null) throw new global::System.ArgumentNullException("store");
DslModeling::RuleManager ruleManager = store.RuleManager;
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.FixUpDiagram));
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.ConnectorRolePlayerChanged));
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemAddRule));
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemDeleteRule));
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemRolePlayerChangeRule));
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemRolePlayerPositionChangeRule));
ruleManager.EnableRule(typeof(global::Altinoren.ActiveWriter.CompartmentItemChangeRule));
}
上面的代码如下:
将新元素添加到图表中(例如,在图表的反序列化期间),触发规则“FixUpDiagram”。
然后规则调用Diagram.FixUpDiagram(parentElement, childElement)
,其中childElement
代表正在添加的元素,parentElement
代表其逻辑父代(使用棘手的条件逻辑确定,所以我没有'尝试自己重现它)。
向下堆栈跟踪FixUpDiagram方法调用图中所有类形状的EnsureCompartments
方法。
EnsureCompartments方法重绘类的隔间,将存根“[ - ]隔间”图形转换为完整的“属性”形状,如上面链接的图片所示。
P.S。史蒂夫,我注意到你确实调用了修复程序,但它仍然没有用。好吧,我不是DSL SDK的专业人士(几天前刚开始使用它),所以无法解释为什么你可能会遇到麻烦。
也许,你用错误的参数调用了fixup。或者可能是Diagram.FixupDiagram(parent,newChild)与parent.FixupChildShapes(newChild)的做法有所不同。然而,这是我的变体,只是工作。希望这也有帮助。
答案 1 :(得分:1)
也许我的答案有点太晚了,但你确认使用DSL Explorer你的隔间有物品吗?