Я недавно столкнулся с проблемой, с которой столкнулся, и сумел заставить ее работать, вот история.
Задача, которую я выполнял, состояла в том, чтобы загрузить и отобразить модель домена и связанную диаграмму, сгенерированную пакетом DSL ActiveWriter.
Вот как я реализовал требуемую функциональность (все методы ниже принадлежат классу 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 (только начал использовать его пару дней назад), поэтому не могу объяснить, почему у вас могут быть проблемы.
Возможно, вы вызвали исправление с неправильными аргументами. Или, возможно, Diagram.FixupDiagram (parent, newChild) делает что-то не так, как родительский.FixupChildShapes (newChild). Однако вот мой вариант, который просто работает. Надеюсь, это также поможет.