我最近遇到了一个相关的问题,并设法使它工作,所以这就是故事。
我正在执行的任务是加载和显示由 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)
, wherechildElement
代表要添加的元素并parentElement
代表其逻辑父级(使用棘手的条件逻辑确定,因此我没有尝试自己重现它)。
向下堆栈跟踪 FixUpDiagram 方法调用EnsureCompartments
图中所有类形状的方法。
EnsureCompartments 方法重绘类的隔间,将存根“[-] 隔间”图形转换为完整的“属性”形状,如上面链接的图片所示。
PS史蒂夫,我注意到你确实调用了修复程序,但它仍然没有工作。好吧,我不是 DSL SDK 的专家(几天前才开始使用它),所以无法解释为什么你可能会遇到麻烦。
也许,您使用错误的参数调用了修复程序。或者,Diagram.FixupDiagram(parent, newChild) 的作用与 parent.FixupChildShapes(newChild) 的作用不同。但是,这是我的变体,它可以正常工作。希望这也有帮助。