Provide an improved user experience to your DSL’s

Posted on September 2, 2009 by

1


Oslo, charming Norwegian city is not only renowned for the cuteness of its female population. One of the most anticipated project from Microsoft Connected System Division is a source of hope but also raises a high level of expectations.  The wait is growing and it fosters impatience, not only because it is not Microsoft’s first shot in dsl area as it has been publishing a DSL Toolkit  for a few years through Visual Studio.

Several press releases help to position these projects or products, far from requesting a single product, it is certain that, from a user perspective, it would be great to have a common module (Windows Modeling Foundation, System.Modeling…) . The argument mostly used by Microsoft’s representatives is that DSL Tools are limited to Visual Studio, this article demonstrates that this argument is mostly driven by marketing considerations.

The goal of this article is to present a way to leverage WPF technology in order to improve your DSL’s editors user experience.

Because of its tight links with Visual Studio, DSL Toolkit did not surf the WinFX wave initiated a few years ago (WCF,WPF, WF). Visual Studio 2010 expected in the next few months should address this area. In the mean time, if you happen to see Oslo’s Quadrant how can someone using DSL Tools not to be tempted to mope around? Quadrant has numerous pros, one of them being that it leverages WPF technology.

A 2008 post presented a first shot at bringing DSL Tools and WPF together: Using WPF As The Designer Surface In DSL Tools

This post raised high hopes but also a fair amount of issues and limitations. It is time to present a minimal solution to address these.

The background leading to bring DSL Tools and WPF emerged when facing limitations and obstacles around complex graphical layout which was an obstacle to its adoption by end users.

The sample

This article is based on a minimalist sample. It is composed of a single concept: Airport and a single relation: Flight (AirportReferencesDestinations).

An airport can be linked to another airport, this relation being a Flight. A rule enforces each Flight to have a corresponding return flight.

image

Figure 1 – AirTraffic Dsl Definition

The Model

The meta-model cannot be easier to draw. One only have to define a custom ConnectionBuilder in order to create the definition of a flight, the return flight as well as a rule managing these flights deletion. Suppressing a flight leads to suppressing automatically its corresponding return flight.

Once these easy steps completed, one only have to trigger code generation, compilation and deployment in order to play with the model editor automatically created.

In no time you end up with a diagram that becomes more convoluted than filling your tax records.

image

Figure 2 – AirTraffic Model

The solution

The basic idea is to have classes generated by DSL Tools (Mexedge.AirTraffic.Dsl) exposing WPF binding mechanism.

Several solution can be foreseen. The obvious one is certainly to generate some code. Because all classes inherits from Microsoft.VisualStudio.Modeling.ModelElement they cannot therefore inherit System.Windows.DependencyObject. However, they can implement System.ComponentModel.INotifyPropertyChanged thus leveraging WPF binding thanks to forward compatibility of existing Windows Forms technology.

But this solution is very intrusive, the DSL project will need to be modified and given the changes announced with Visual Studio 2010, the less intrusive you get, the smoother the transition to Visual Studio 2010 and its DSL Tools will be.

This being said, the scope of solutions drastically reduced. However, WPF binding leverages several mechanisms to bind data. Indeed, don’t you ever wondered how some classes which did not implement any interface or inherit and class can still be bound to WPF controls ?  You wouldn’t be the only one: Data binding without INotifyPropertyChanged

Don’t you think that it seems like a good path to follow? We will take advantage of the mechanisms surrounding System.ComponentModel.TypeDescriptionProvider class.

Following another interesting link: Optimizing Performance: Data Binding

But far from wanting to resort to code generation and thus the use of the attribute
System.ComponentModel.TypeDescriptionProviderAttribute, salvation will come from the method System.ComponentModel.TypeDescriptor.AddProvider.

Indeed, thanks to this method, the required behavior will be added dynamically to our classes therefore preventing any constraint on their design.

TypeDescriptionProvider

When loading a model, each class will be given a TypeDescriptionProvider. To do so, the model’s metadata dictionary provided through DSL Toolkit will be leveraged.

Our TypeDescriptionProvider class named BindingTypeDescriptionProvider will be in charge of creating, if required, an ICustomTypeDescriptor for a given instance of a ModelElement.

ICustomTypeDescriptor

Users familiar with DSL Toolkit know the mechanisms around TypeDescriptionProvider. Indeed, they are the one allowing personalizing the property grid associated to  a concept or a relation. We will use Microsoft.VisualStudio.Modeling.Design.ElementTypeDescriptor and Microsoft.VisualStudio.Modeling.Design.ElementPropertyDescriptor offered by DSL Toolkit in our quest to provide data binding.  Our implementation of ICustomTypeDescriptor interface named BindingTypeDescriptor will inherit from
Microsoft.VisualStudio.Modeling.Design.ElementTypeDescriptor class.

Given this choice, we are structuring both implementation and development. We will divide those based on the nature of the property to bind; and thanks to the metadata put in place by DSL Toolkit will be able to identify the nature of any given property.

PropertyDescriptor

We need to provide 3 PropertyDescriptors, each one targeting a specific kind of property:

  • DomainPropertyPropertyDescriptor: simple types (string …) properties that are not linked to relations between concepts,
  • IsOneDomainRolePropertyDescriptor: properties addressing relations with multiplicity 1,
  • IsManyDomainRolePropertyDescripor: properties addressing  relations with multiplicity n

Whatever PropertyDescriptor, the postulate is to provide a bidirectional mechanism,
OnValueChanged method implemented by them should be executed if the value of the property to which they are associated changes.  To do so, we are going to leverage DSL Toolkit’s supervision module. For instance, as soon as the value of a simple type property is changed, the relevant OnValueChanged method must be executed. For other properties, different events are available; it is up to us to subscribe to the relevant ones.

Properties addressing relations with multiplicity n requires special attention. Indeed, they are materialized by a collection (Microsoft.VisualStudio.Modeling.LinkedElementCollection<T>) that is nothing close to what WPF would expect.  We therefore have to act as a mediator between LinkedElementCollection<T> and ObservableCollection<T>. The class named BindingLinkedElementCollection has been created to address this special need, leveraging events exposed by DSL Toolkit.

Once these several classes developped, work is done.

The realization

A video illustrating the result of this development is available. The source code illustrating this article is freely available. The Visual Studio solution composed of 3 modules:

  • AirReader: this is a WPF application that offers a new user experience to edit the AirTraffic model, this project leverages the Kevin’s bag’o’tricks library weel known by WPF afficionados, and Bea Stollnitz wpf drag’n’drop solution.
  • Dsl: this is composed of 2 projects Dsl and DslPackage defining the AirTraffic metamodel,
  • Miami: this project Miami.Modelling.Sdk contains, among other things, the code presented in this paper.

The Miami module also addresses the use of DSL Tools outside Visual Studio. To do so, it offers a Repository class allowing loading and saving a model but also activating databinidng.

Thus, loading a model and bind it is reduced to the following lines of code:

DslBundle l_dslBundle = new DslBundle(fileName, typeof(AirTrafficDomainModel));
DslSettings l_dslSettings = new DslSettings() { IsBindable = true };
m_repository = new Repository(l_dslBundle, l_dslSettings);
Traffic l_traffic = (Traffic)m_repository.Load();
this.DataContext = l_traffic;

Saving a model is even easier:

m_repository.Save();

This module also offers other functionalities.

image

Figure 3 – AirReader: WPF AirTraffic DSL Editor

What’s next?

If in the name of experimentation, this article shed some light on using DSL Toolkit outside Visual Studio, developing a WPF based model editor integrating this technology is envisioned. This is the direction that Visual Studio 2010 is taking. It should be the subject of a next article, unless the next subject becomes the personalization of the Store class inside Visual Studio. Indeed, several mechanisms allow taking control of it in order to open up the model to modifications triggered by
external events (a real time collaboration scenario for instance).

We could also deal with another Oslo’s technical pillar that makes DSL Toolkit users jealous: the database. The various events exposed by DSL Toolkit allows saving modifications into a database instead of or in conjunction (for logging) to the file system offering numerous advantages (replay, collaboration etc…).


Download the complete solution here.

A pdf version of the article is available here.


Creative Commons License
AirTraffic by MEXEDGE is licensed under a Creative Commons Attribution-NonCommercial 3.0 Unported License.
Based on a work at www.netfxfactory.org.

Tagged: , ,
Posted in: Modeling