Créer un langage spécifique à un domaine basé sur Windows Forms

Vous pouvez utiliser Windows Forms pour afficher l'état d'un modèle de langage spécifique à un domaine (DSL), au lieu d'utiliser un diagramme DSL. Cette rubrique vous explique comment lier un élément Windows Form à un élément DSL à l'aide du SDK de visualisation et de modélisation de Visual Studio.

L'image suivante montre une interface utilisateur Windows Form et l'explorateur de modèles pour une instance DSL :

DSL instance in Visual Studio

Créer un DSL Windows Forms

Le modèle DSL Concepteur WinForm minimal crée un DSL minimal que vous pouvez modifier selon vos propres besoins.

  1. Créez un DSL à partir du modèle Concepteur WinForm minimal.

    Dans cette procédure pas à pas, les noms suivants sont supposés :

    • Solution et nom du DSL : FarmApp
    • Espace de noms : Company.FarmApp
  2. Testez l’exemple initial fourni par le modèle :

    1. Transformez tous les modèles.

    2. Générez et exécutez l’exemple (Ctrl+F5).

    3. Dans l’instance expérimentale de Visual Studio, ouvrez le fichier Sample dans le projet de débogage.

      Notez qu’il est affiché dans un contrôle Windows Forms.

      Vous pouvez également voir les éléments du modèle affichés dans l’Explorateur.

      Ajoutez des éléments dans le formulaire ou dans l’Explorateur : notez qu’ils apparaissent dans l’autre affichage.

    Dans l’instance principale de Visual Studio, notez les points suivants concernant la solution DSL :

  • DslDefinition.dsl ne contient aucun élément de diagramme. Cela est dû au fait que vous n’utiliserez pas de diagrammes DSL pour afficher les modèles d’instance de ce DSL. Au lieu de cela, vous allez lier un Windows Form au modèle, et les éléments du formulaire afficheront le modèle.

  • Outre les projets Dsl et DslPackage, la solution contient un troisième projet nommé UI.UI, qui contient la définition d’un contrôle Windows Forms. DslPackage dépend de UI, et UI dépend de Dsl.

  • Dans le projet DslPackage, UI\DocView.cs contient le code qui affiche le contrôle Windows Forms défini dans le projet UI.

  • Le projet UI contient un exemple fonctionnel de contrôle de formulaire lié au DSL. Cependant, il ne fonctionnera pas si vous avez modifié la définition du DSL. Le projet UI contient les éléments suivants :

    • Une classe Windows Forms nommée ModelViewControl.

    • Un fichier nommé DataBinding.cs, contenant une définition partielle supplémentaire de ModelViewControl. Pour afficher son contenu, dans l'Explorateur de solutions, ouvrez le menu contextuel du fichier et choisissez Afficher le code.

À propos du projet UI

Lorsque vous mettez à jour le fichier de définition DSL pour définir votre propre DSL, vous devez mettre à jour le contrôle dans le projet UI pour afficher votre DSL. Contrairement aux projets Dsl et DslPackage, l’exemple de projet UI n'est pas généré à partir de DslDefinitionl.dsl. Vous pouvez ajouter des fichiers .tt pour générer le code si vous le souhaitez, bien que cela ne soit pas abordé dans ce guide.

Mettre à jour la définition DSL

L'image suivante est la définition DSL utilisée dans ce guide.

DSL definition

  1. Ouvrez DslDefinition.dsl dans le concepteur DSL.

  2. Supprimer ExampleElement

  3. Renommez la classe de domaine ExampleModel en Farm.

    Attribuez-lui les propriétés de domaine supplémentaires Size de type Int32, et IsOrganic de type Boolean.

    Notes

    Si vous supprimez la classe de domaine racine et que vous créez ensuite une nouvelle racine, vous devrez réinitialiser la propriété Classe racine de l’éditeur. Dans l'Explorateur DSL, sélectionnez Éditeur. Ensuite, dans la fenêtre Propriétés, définissez Classe racine sur Farm.

  4. Utilisez l'outil Classe de domaine nommée pour créer les classes de domaine suivantes :

    • Field - Attribuez-lui une propriété de domaine supplémentaire nommée Size.

    • Animal - Dans la fenêtre Propriétés, définissez Modificateur d'héritage sur Abstrait.

    Notes

    L'outil Classe de domaine nommée et les autres outils mentionnés dans cette section se trouvent dans la fenêtre outils Boîte à outils. Vous pouvez ouvrir ou masquer cette fenêtre à l'aide du menu Affichage>Boîte à outils.

  5. Utilisez l'outil Classe de domaine pour créer les classes suivantes :

    • Sheep

    • Goat

  6. Utilisez l'outil Héritage pour faire hériter Goat et Sheep de Animal.

  7. Utilisez l'outil Incorporation pour incorporer Field et Animal sous Farm.

  8. Il est judicieux de mettre de l'ordre dans le diagramme. Pour réduire le nombre d'éléments dupliqués, utilisez la commande Bring Subtree Here dans le menu contextuel des éléments feuilles.

  9. Transformer tous les modèles dans la barre d’outils de l’Explorateur de solutions.

  10. Générez le projet Dsl.

    Notes

    À ce stade, les autres projets ne se généreront pas sans erreurs. Cependant, nous voulons générer le projet Dsl afin que son assembly soit disponible pour l'Assistant Source de données.

Mettre à jour le projet UI

Vous pouvez maintenant créer un nouveau contrôle utilisateur qui affichera les informations stockées dans le modèle DSL. La façon la plus simple de connecter le contrôle utilisateur au modèle est d'utiliser des liaisons de données. Le type d'adaptateur de liaison de données appelé ModelingBindingSource est spécifiquement conçu pour connecter les DSL aux interfaces non VMSDK.

Définir votre modèle DSL comme source de données

  1. Dans le menu Données , choisissez Afficher les sources de données.

    La fenêtre Sources de données s’ouvre.

    Choisissez Ajouter une nouvelle source de données. L’Assistant Configuration de source de données s’ouvre.

  2. Choisissez Objet, Suivant.

    Développez Dsl, Company.FarmApp, puis sélectionnez Farm, qui représente la classe racine de votre modèle. Cliquez sur Terminer.

    Dans l’Explorateur de solutions, le projet UI contient maintenant Properties\DataSources\Farm.datasource

    Les propriétés et les relations de votre classe de modèle apparaissent dans la fenêtre Sources de données.

    Data sources window

Connecter votre modèle à un formulaire

  1. Dans le projet UI, supprimez tous les fichiers .cs existants.

  2. Ajoutez un nouveau fichier Contrôle utilisateur nommé FarmControl au projet UI.

  3. Dans la fenêtre Sources de données, dans le menu déroulant Farm, choisissez Détails.

    Conservez les paramètres par défaut pour les autres propriétés.

  4. Ouvrez FarmControl.cs en mode Création.

    Faites glisser l’élément Farm de la fenêtre Sources de données vers FarmControl.

    Un ensemble de contrôles s’affiche, un pour chaque propriété. Les propriétés de relation ne génèrent pas de contrôles.

  5. Supprimez farmBindingNavigator. Cet élément est également généré automatiquement dans le concepteur FarmControl, mais il n’est pas utile pour cette application.

  6. À l’aide de la boîte à outils, créez deux instances de DataGridView, puis nommez-les AnimalGridView et FieldGridView.

    Notes

    Une autre étape consiste à faire glisser les éléments Animals et Fields de la fenêtre Sources de données vers le contrôle. Cette action crée automatiquement des grilles de données et des liaisons entre le mode Grille et la source de données. Mais cette liaison ne fonctionne pas correctement pour les DSL. Par conséquent, il est préférable de créer manuellement les grilles de données et les liaisons.

  7. Si la boîte à outils ne contient pas l’outil ModelingBindingSource, ajoutez-le. Dans le menu contextuel de l’onglet Données, sélectionnez Choisir les éléments. Dans la boîte à outils Choisir des éléments de boîte à outils, sélectionnez ModelingBindingSource dans l’onglet .NET Framework.

  8. À l’aide de la boîte à outils, créez deux instances de ModelingBindingSource, puis nommez-les AnimalBinding et FieldBinding.

  9. Définissez la propriété DataSource de chaque instance ModelingBindingSource sur farmBindingSource.

    Définissez la propriété DataMember sur Animals ou Fields.

  10. Définissez les propriétés DataSource de AnimalGridView sur AnimalBinding, et de FieldGridView sur FieldBinding.

  11. Ajustez la disposition du contrôle Farm à votre convenance.

    ModelingBindingSource est un adaptateur qui exécute plusieurs fonctions spécifiques aux DSL :

  • Il encapsule les mises à jour dans une transaction de magasin VMSDK.

    Par exemple, lorsque l'utilisateur supprime une ligne de la grille d’affichage des données, une liaison normale entraînerait une exception de transaction.

  • Cela garantit que, lorsque l'utilisateur sélectionne une ligne, la fenêtre Propriétés affiche les propriétés de l'élément de modèle correspondant, au lieu de la ligne de la grille de données.

    Schema of the DSL binding

    Schéma des liens entre les sources de données et les vues.

Terminer les liaisons au DSL

  1. Ajoutez le code suivant dans un fichier de code distinct dans le projet UI :

    using System.ComponentModel;
    using Microsoft.VisualStudio.Modeling;
    using Microsoft.VisualStudio.Modeling.Design;
    
    namespace Company.FarmApp
    {
      partial class FarmControl
      {
        public IContainer Components { get { return components; } }
    
        /// <summary>Binds the WinForms data source to the DSL model.
        /// </summary>
        /// <param name="nodelRoot">The root element of the model.</param>
        public void DataBind(ModelElement modelRoot)
        {
          WinFormsDataBindingHelper.PreInitializeDataSources(this);
          this.farmBindingSource.DataSource = modelRoot;
          WinFormsDataBindingHelper.InitializeDataSources(this);
        }
      }
    }
    
  2. Dans le projet DslPackage, éditez le fichier DslPackage\DocView.tt pour mettre à jour la définition de variable suivante :

    string viewControlTypeName = "FarmControl";
    

Tester le DSL

La solution DSL peut maintenant générer et exécuter, bien que vous souhaitiez peut-être ajouter d’autres améliorations ultérieurement.

  1. Créez et exécutez la solution.

  2. Dans l’instance expérimentale de Visual Studio, ouvrez le fichier Sample.

  3. Dans l’Explorateur FarmApp, ouvrez le menu contextuel du nœud racine Farm, puis choisissez Add New Goat.

    Goat1 apparaît dans la vue Animals.

    Avertissement

    Vous devez utiliser le menu contextuel du nœud Farm, pas celui du nœud Animals.

  4. Sélectionnez le nœud racine Farm et affichez ses propriétés.

    Dans la vue du formulaire, modifiez le champ Name ou Size de la ferme.

    Lorsque vous vous éloignez de chaque champ du formulaire, la propriété correspondante est modifiée dans la fenêtre Propriétés.

Améliorer le DSL

Mettre immédiatement à jour les propriétés

  1. En mode Conception dans le fichier FarmControl.cs, sélectionnez un champ simple tel que Name, Size ou IsOrganic.

  2. Dans la fenêtre Propriétés, développez DataBindings et ouvrez (Advanced).

    Dans la boîte de dialogue Mise en forme et liaison avancée, sous Mode de mise à jo&ur de la source de données, choisissez OnPropertyChanged.

  3. Créez et exécutez la solution.

    Vérifiez que lorsque vous modifiez le contenu du champ, la propriété correspondante du modèle Farm change aussitôt.

Fournir des boutons Ajouter

  1. En mode Conception du fichier FarmControl.cs, utilisez la boîte à outils pour créer un bouton sur le formulaire.

    Modifiez le nom et le texte du bouton, par exemple en New Sheep.

  2. Ouvrez le code du bouton (par exemple en double-cliquant dessus).

    Modifiez-le comme suit :

    private void NewSheepButton_Click(object sender, EventArgs e)
    {
      using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep"))
      {
        elementOperations.MergeElementGroup(farm,
          new ElementGroup(new Sheep(farm.Partition)));
        t.Commit();
      }
    }
    
    // The following code is shared with other add buttons:
    private ElementOperations operationsCache = null;
    private ElementOperations elementOperations
    {
      get
      {
        if (operationsCache == null)
        {
          operationsCache = new ElementOperations(farm.Store, farm.Partition);
        }
        return operationsCache;
      }
    }
    private Farm farm
    {
      get { return this.farmBindingSource.DataSource as Farm; }
    }
    

    Vous devez également insérer la directive suivante :

    
    using Microsoft.VisualStudio.Modeling;
    
  3. Ajouter des boutons similaires pour les champs Goats et Fields.

  4. Créez et exécutez la solution.

  5. Vérifiez que le nouveau bouton ajoute un élément. Le nouvel élément doit apparaître à la fois dans l'Explorateur FarmApp et dans la vue de grille de données appropriée.

    Vous devriez pouvoir modifier le nom de l'élément dans la vue de grille de données. Vous pouvez également le supprimer à cet endroit.

    Sample data grid view

À propos du code pour ajouter un élément

Pour les boutons des nouveaux éléments, le code alternatif suivant est légèrement plus simple.

private void NewSheepButton_Click(object sender, EventArgs e)
{
  using (Transaction t = farm.Store.TransactionManager.BeginTransaction("Add sheep"))
  {
    farm.Animals.Add(new Sheep(farm.Partition)); ;
    t.Commit();
  }
}

Mais ce code ne définit pas de nom par défaut pour le nouvel élément. Il n'exécute aucune fusion personnalisée que vous auriez pu définir dans les directives de fusion d’éléments du DSL, ni aucun code de fusion personnalisé qui aurait pu être défini.

C'est pourquoi nous vous recommandons d’utiliser ElementOperations pour créer de nouveaux éléments. Pour plus d’informations, consultez Personnalisation de la création et du déplacement des éléments.