Problem with custom editor

May 31, 2007 at 9:25 AM
Hi!

I just started to use the DSL Editor Power toy. I was happy to see this new package, because I had really needed to create custom editor for my DSL.
I am working on a UI Process DSL, helping to design the navigation between ASP.NET pages.

For the links representing navigations on the DSL editor I want to introduce a custom editor so that users of DSL can add one or more user role to a navigation.
I started to experiment with the Editor Power toy and could easily create a custom editor.
Here is the code for the user control:

namespace Espirit.WebUiWorkflow.DslEditorPowerToy.Controls
{
public partial class NavigationLinkEditor : UserControl, IMonitorSelection
{
NavigationLink selectedLink;

public NavigationLinkEditor()
{
InitializeComponent();
}



#region IMonitorSelection Members

public void NotifySelectionChanged(ISelectionProvider selectionProvider, SelectionChangeSource source)
{

if (ModelHelper.GetRepresentedElement(selectionProvider.PrimarySelection) is NavigationLink)
{
selectedLink = (NavigationLink)ModelHelper.GetRepresentedElement(selectionProvider.PrimarySelection);
this.linkNameTextBox.Text = selectedLink.NavigationName;
}
else
{
this.NavigationNameLabel.Text = "";
}
}

#endregion

private void button1_Click(object sender, EventArgs e)
{
if (selectedLink != null)
{
selectedLink.NavigationName = "aaa";
}

}
}
}

Within the user control I keep a reference to the currently selected DSL element. (Namely NavigaionLink)

The problem occurres when I want set the Name property of the selected Navigation link. I get the message from Vista : "Visual Studio has stopped woring".
In the event log I can find this:
Faulting application devenv.exe, version 8.0.50727.867, time stamp 0x45d2c842, faulting module kernel32.dll, version 6.0.6000.16386, time stamp 0x4549bd80, exception code 0xe0434f4d, fault offset 0x0001b09e, process id 0xcf4, application start time 0x01c7a35bf8dbd655.

What can be the problem?

Greetings, Ferenc (Frank) Kiss

ToolWindowEx.cs contains this code:
namespace Espirit.WebUiWorkflow.DslEditorPowerToy.Controls
{
internal partial class WebUiWorkflowDslEditorToolWindow : WebUiWorkflowDslEditorToolWindowBase
{
NavigationLinkEditor linkEditor;

protected override System.Windows.Forms.Control Control
{
get
{
if (linkEditor == null)
{
linkEditor = new NavigationLinkEditor();
}
return linkEditor;
}
}

}
}
Coordinator
May 31, 2007 at 2:04 PM
Edited May 31, 2007 at 6:49 PM
OK, I got to the bottom of this.

It seems I did not reproduce this right on my normal machine. So I did it on a Vista machine for you to be sure.
As it turns out nothing to do with Vista. You have encountered one of the fundemntals to manipulating DSL models programmatically (i.e. Store Transactions).
Basically you must always be within a transaction scope when modifying the store. (This is a very powerful and necessary design feature of the DSL tools!!!) see Writing Changes to the Store for more details.


I have posted the solution for you below.

cheers

Reproduction


OK here is what I did to try and repro this issue.

  • Installed brand new version of Vista Ultimate.
(Performed the following as an admin user, with UAC turned ON.)
  • Windows Update
  • Installed brand new version of Visual Studio 2005 (Team Edition for Software Architects)
  • Installed VS Service Pack 1
  • Installed VS Vista Update
  • Installed VSSDK (v.4) (Feb2007) (From Here)
  • Installed GAX/GAT (1.2) (Feb2007 CTP) (From Here)
  • Windows Update
  • Installed DSL Editor PowerToy (DEPT) (v.1.1) (From Here)

Development

Doing the following running devenv.exe 'Run as Adminstrator'
  • Created a 'DSL Project', minimal language, (mydsl1), all default options
  • Associated DEPT Guidance Package to DSL Solution
  • Added 'DSL Editors' using DEPT from context menu on DSL Solution
  • Create a new UserControl in DslPackage project (MyCustomEditor.cs)
  • Added a Label, TextBox and Button to control as your code indicates
  • Added your code, with following modifications.
    • Replaced references to 'NavigationLink' with 'ExampleElement' from the minimal language dsl
    • Added a domain prooperety 'NavigationName' to domainclass 'ExampleElement' on DSL model
  • Configured a single editor in EditorDefinitions.deptec, and used new editor as the EditorControl property

Noticed at this point you have extended ToolWindow.cs, which indicated to me you are not using latest version of PowerToy, perhaps you are using 1.0 version???

Continued. No changes to ToolWindow.cs (not required in current version (v.1.1))

  • Transformed Templates
  • Rebuild Solution
  • F5 to debug

Debugging


-> Visual Studio Experimental is opened, (assume not running as administrative user.)

  • Opened Sample.mydsl1
  • Selected first instance of ExampleElement shape on diagram, verified getting notified of selection changed events in MyCustomEditor.cs
  • In the 'Properties Window' of the IDE, updated value of 'Navigation Name' property on selected shape
  • Selected diagram
  • Selected same instance of ExampleElement, verified label in editor is updated with value from 'Navigation Name' property of ExampleElement
  • In ToolWindow, clicked the button, verified button click handler fired and call to set the label text.
-> Visual Studio (experimental debugged instance) crashes with described error!!!!, and restarts!

Verify

  • Ran tests again, same problem repro consistently
  • Stepped through the call to update the 'Navigation Name' property of ExampleElement, this code is generated in Dsl project. Arrive at method: ExampleElement.NavigationNamePropertyHandler.SetValue(), where the code crashes on ValueChanging() method.

  • Caught thrown exception,
System.InvalidOperationException was caught
  Message="This operation can only be performed within the context of a modeling transaction."
  Source="Microsoft.VisualStudio.Modeling.Sdk"
  StackTrace:
       at Microsoft.VisualStudio.Modeling.ErrorHandler.ThrowIfNotInState(Store store, StoreStates states)
       at Microsoft.VisualStudio.Modeling.ErrorHandler.ThrowIfNotInState(Partition parition, StoreStates states)
       at Microsoft.VisualStudio.Modeling.DomainPropertyValueHandler`2.ValueChanging(TElement element, TValue oldValue, 
 
TValue newValue)
       at Company.Language1.ExampleElement.NavigationNamePropertyHandler.SetValue(ExampleElement element, String 
 
newValue)
       at Company.Language1.ExampleElement.set_NavigationName(String value)
       at Company.Language1.DslEditors.MyCustomEditor.button1_Click(Object sender, EventArgs e)

Conclusion:

This exception is by design of the DSL Tools. All updates to DSL models must be done within the scope of a transaction.

To get this code working do the following changes:
In your handler for the button click, add the following code:

        private void button1_Click(object sender, EventArgs e)
        {
            if (selectedLink != null)
            {
                using (Transaction transaction = selectedLink.Store.TransactionManager.BeginTransaction("Navigation 
 
Name Update"))
                {
                    selectedLink.NavigationName = "aaa";
                    transaction.Commit();
                }
            }
        }

May 31, 2007 at 4:04 PM
Using code in concluson worked.
I have the same configuration as you installed. Using Transaction corrected the error.

I have also removed the ToolWindows exension (as I uses 1.1 too) and rather configured EditorsDefinition.

Thaks for the help,
Ferenc
Coordinator
May 31, 2007 at 6:46 PM
Edited May 31, 2007 at 6:49 PM
My pleasure.

There is one related bug with the v.1.1 release that we have fixed now, but we won't have a release for a little while, you might want to fix it by hand.

It concerns the code that is generated for each editor configured in the DslEditorsDefinitions.deptec.
If you look at the Editors.tt text template in the GeneratedCode folder, the PowerToy installs, you will notice that the Control property instantiates the editor control each time it is accessed. Clearly this is an oversight on performance, and a waste of resources.
        public override global::System.Windows.Forms.Control Control
        {
            get
            {
                return new global::<#= editor.EditorControl #>();
            }
        }

We have corrected this in later changesets, but you might want to make these changes to your text template file (Editors.tt) until we have a new release.
        private global::System.Windows.Forms.Control _editorControl = null;
 
        public override global::System.Windows.Forms.Control Control
        {
            get
            {
                if (null == this._editorControl)
                    this._editorControl = new global::<#= editor.EditorControl #>();
                return this._editorControl;
            }
        }

I believe this should help you.