我最近遇到了一个相关的问题,并设法让它发挥作用,所以故事是这样的。
我执行的任务是加载和显示一个域模型以及由ActiveWriter的DSL包生成的关联图。
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);
}
这些东西工作得很好:它正确地从VisualStudio创建的文件中加载了图表,在我的自定义windows窗体中绘制了图表,支持滚动画布,甚至允许我在这里拖动形状。然而,有一件事困扰着我——隔间是空的,有默认名称,即“隔间”。
谷歌根本帮不上忙,所以我不得不自己动手。这不是很容易,但在Reflector的帮助下,在花了几个小时后,我成功地使这个场景如预期的那样工作!
幸运的是,我们甚至不需要编写任何代码,因为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
图中所有类形状的方法。
-
EnsureRecompartments方法重新绘制类的分区,将存根“[-]分区”图形转换为完整的“属性”形状,如上面链接的图片所示。
也许,你用错误的论点进行了修正。或者可能是Diagram.FixupDiagram(parent,newChild)的功能与parent.FixupChildShapes(newChild)的功能不同。然而,这里是我的变体,它刚刚起作用。希望这也有帮助。