Comment : définir une commande de menu sur un diagramme de modélisation

Dans Visual Studio Ultimate, vous pouvez définir des éléments de menu supplémentaires qui apparaîtront lorsque l'utilisateur cliquera avec le bouton droit sur un diagramme UML. Vous pouvez contrôler si la commande de menu apparaît et est activée lorsque l'utilisateur clique avec le bouton droit sur tout élément sur le diagramme, et vous pouvez écrire un code qui s'exécute lorsque l'utilisateur sélectionne l'élément de menu. Vous pouvez empaqueter ces extensions dans une extension d'intégration Visual Studio (VSIX) et la distribuer à d'autres utilisateurs Visual Studio Ultimate.

Configuration requise

Définition de la commande de menu

Pour créer une commande de menu pour un concepteur UML, vous devez créer une classe qui définisse le comportement de la commande et incorporer cette classe dans une extension d'intégration Visual Studio (VSIX). L'extension d'intégration Visual Studio (VSIX) joue le rôle d'un conteneur capable d'installer la commande. Il existe deux autres méthodes permettant de définir une commande de menu :

  • Créez une commande de menu dans son propre projet VSIX à l'aide d'un modèle de projet. Il s'agit de la méthode la plus rapide. Choisissez cette méthode si vous ne souhaitez pas combiner vos commandes de menu avec d'autres types d'extensions, telles que les extensions de validation, les éléments de boîte à outils personnalisés ou les gestionnaires de mouvements.

  • Créez séparément les commandes de menu et les projets VSIX. Choisissez cette méthode si vous souhaitez combiner plusieurs types d'extensions au sein d'un même projet VSIX. Par exemple, si votre commande de menu prévoit que le modèle observe des contraintes spécifiques, vous pouvez l'incorporer au même projet VSIX en tant que méthode de validation.

Pour créer une commande de menu dans son propre projet VSIX

  1. Dans la boîte de dialogue Nouveau projet, sous Modèles installés, sélectionnez Extension de commande.

  2. Ouvrez le fichier .cs du nouveau projet et modifiez la classe CommandExtension pour implémenter votre commande.

    Pour plus d'informations, consultez Implémentation de la commande de menu.

  3. Vous pouvez ajouter des commandes supplémentaires à ce projet en définissant de nouvelles classes.

  4. Testez la commande de menu en appuyant sur F5. Pour plus d'informations, consultez Exécution de la commande de menu.

  5. Installez la commande de menu sur un autre ordinateur en copiant le fichier bin\*\*.vsix généré par votre projet. Pour plus d'informations, consultez Installation de la commande de menu.

Pour créer une commande de menu distincte dans un projet de bibliothèque de classes (DLL)

  1. Créez un projet de bibliothèque de classes dans une nouvelle solution Visual Studio ou dans une solution existante.

    1. Dans le menu Fichier, pointez sur Nouveau, puis cliquez sur Projet.

    2. Sous Modèles installés, cliquez sur Visual C# ou sur Visual Basic. Dans la colonne du milieu, cliquez sur Bibliothèque de classes.

    3. Définissez Solution pour indiquer si vous voulez créer une nouvelle solution ou ajouter un composant à une solution VSIX que vous avez déjà ouverte.

    4. Définissez le nom et l'emplacement du projet, puis cliquez sur OK.

  2. Ajoutez les références suivantes à votre projet.

    Référence

    Actions autorisées

    System.ComponentModel.Composition

    Définissez des composants à l'aide de Managed Extensibility Framework (MEF) (page éventuellement en anglais).

    Microsoft.VisualStudio.Uml.Interfaces

    Lisez et modifiez des propriétés d'éléments de modèles.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Créez des éléments de modèles et modifiez les formes dans les diagrammes.

    Microsoft.VisualStudio.Modeling.Sdk.10.0

    Définissez des gestionnaires d'événements de modèle.

    Encapsulez des séries de modifications dans votre modèle. Pour plus d'informations, consultez Comment : lier des mises à jour de modèles à l'aide de transactions.

    Microsoft.VisualStudio.Modeling.Sdk.Diagrams.10.0

    (pas toujours requis)

    Accédez à des éléments de diagramme supplémentaires pour les gestionnaires de mouvements.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer

    Nécessaire uniquement pour les commandes des diagrammes de couche. Pour plus d'informations, consultez Création d'extensions de diagrammes de couche.

    Définissez des commandes sur un diagramme de couche.

  3. Ajoutez au projet un fichier de classe comportant le code suivant.

    Notes

    Adaptez l'espace de noms, le nom de la classe et la valeur retournée par Text à vos besoins.

    using System.ComponentModel.Composition;   
    using System.Linq;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
    using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
    using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
    using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
    using Microsoft.VisualStudio.Uml.Classes; 
        // ADD other UML namespaces if required
    
    namespace UMLmenu1 // CHANGE
    {
      // DELETE any of these attributes if the command
      // should not appear in some types of diagram.
      [ClassDesignerExtension]
      [ActivityDesignerExtension]
      [ComponentDesignerExtension]
      [SequenceDesignerExtension]
      [UseCaseDesignerExtension]
      // [LayerDesignerExtension] // if you have installed Feature Pack 1
    
      // All menu commands must export ICommandExtension:
      [Export (typeof(ICommandExtension))]
      // CHANGE class name
      public class Menu1 : ICommandExtension
      {
        [Import]
        public IDiagramContext DiagramContext { get; set; }
    
        public void QueryStatus(IMenuCommand command)
        { // Set command.Visible or command.Enabled to false
          // to disable the menu command.
          command.Visible = command.Enabled = true;
        }
    
        public string Text
        {
          get { return "MENU COMMAND LABEL"; }
        }
    
        public void Execute(IMenuCommand command)
        {
          // A selection of starting points:
          IDiagram diagram = this.DiagramContext.CurrentDiagram;
          foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>())
          { IElement element = shape.Element; }
          IModelStore modelStore = diagram.ModelStore;
          IModel model = modelStore.Root;
          foreach (IElement element in modelStore.AllInstances<IClass>()) 
          { }
        }
      }
    }
    

    Pour plus d'informations sur les éléments à ajouter dans les méthodes, consultez Implémentation de la commande de menu.

Vous devez ajouter votre commande de menu à un projet VSIX, qui jouera le rôle de conteneur pour l'installation de la commande. Si vous le souhaitez, vous pouvez inclure d'autres composants dans le même fichier VSIX.

Pour ajouter une commande de menu distincte à un projet VSIX

  1. Cette procédure n'est pas nécessaire si vous avez créé la commande de menu avec son propre VSIX.

  2. Créez un projet VSIX, sauf si votre solution en comporte déjà un.

    1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur la solution, pointez sur Ajouter, puis cliquez sur Nouveau projet.

    2. Sous Modèles installés, développez Visual C# ou Visual Basic, puis cliquez sur Extensibilité. Dans la colonne centrale, cliquez sur Projet VSIX .

  3. Définissez le projet VSIX comme projet de démarrage de la solution.

    Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet VSIX, puis cliquez sur Définir comme projet de démarrage.

  4. Dans source.extension.vsixmanifest, sous Contenu, ajoutez un projet de bibliothèque de classes en tant que composant MEF.

    1. Ouvrez source.extension.vsixmanifest.

    2. Cliquez sur Ajouter du contenu.

    3. Dans Sélectionner un type de contenu, sélectionnez Composant MEF.

    4. Dans Sélectionner une source, cliquez sur Projet, puis sélectionnez le nom de votre projet de bibliothèque de classes.

  5. Cliquez sur Sélectionner des éditions, puis sélectionnez les éditions de Visual Studio sur lesquelles vous voulez que votre extension s'exécute.

  6. Définissez le nom et les champs descriptifs du projet VSIX. Enregistrez le fichier.

Implémentation de la commande de menu

La classe de la commande de menu implémente les méthodes requises pour ICommandExtension.

string Text { get; }

Retournez l'étiquette de votre élément de menu.

void QueryStatus(IMenuCommand command);

Appelée lorsque l'utilisateur clique avec le bouton droit dans le diagramme.

Cette méthode ne doit pas modifier le modèle.

Utilisez DiagramContext.CurrentDiagram.SelectedShapes pour déterminer si vous souhaitez que la commande apparaisse et soit activée.

Définissez :

  • command.Visible sur true si la commande doit s'afficher dans le menu lorsque l'utilisateur clique avec le bouton droit sur le diagramme.

  • command.Enabled sur true si l'utilisateur peut cliquer sur la commande dans le menu.

  • command.Text pour définir l'étiquette de menu dynamiquement.

void Execute (IMenuCommand command);

Appelé lorsque l'utilisateur clique sur votre élément de menu, s'il est visible et activé.

 

Accès au modèle dans le code

Incluant la déclaration suivante dans votre classe de commande de menu :

[Import] public IDiagramContext DiagramContext { get; set; }

...

La déclaration d'IDiagramContext vous permet d'écrire du code dans vos méthodes qui accède au diagramme, à la sélection actuelle et au modèle :

IDiagram diagram = this.DiagramContext.CurrentDiagram;
foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>())
{ IElement element = shape.Element; ... }
IModelStore modelStore = diagram.ModelStore;
IModel model = modelStore.Root;
foreach (IElement element in modelStore.AllInstances<IUseCase>()) {...}

Accès au modèle et mise à jour du modèle

Les éléments du modèle UML sont tous disponibles via l'API. À partir de la sélection actuelle ou de la racine du modèle, vous pouvez accéder à tous les autres éléments. Pour plus d'informations, consultez Comment : naviguer dans le modèle UML et Programmation à l'aide de l'API UML.

Si vous utilisez un diagramme de séquence, consultez également Comment : modifier des diagrammes de séquence à l'aide de l'API UML.

L'API vous permet également de modifier les propriétés des éléments, de supprimer des éléments et des relations, ainsi que de créer de nouveaux éléments et relations.

Par défaut, chaque modification que vous apportez dans votre méthode Execute sera exécutée dans une transaction distincte. L'utilisateur sera en mesure d'annuler chaque modification séparément. Si vous souhaitez grouper les modifications dans une transaction unique, utilisez un ILinkedUndoTransaction comme cela est décrit dans Comment : lier des mises à jour de modèles à l'aide de transactions.

Utilisation du thread d'interface utilisateur pour les mises à jour

Dans certains cas, il peut s'avérer utile d'actualiser un modèle à partir d'un thread d'arrière-plan. Par exemple, si votre commande charge des données à partir d'une ressource lente, vous pouvez effectuer ce chargement dans un thread d'arrière-plan, de sorte que l'utilisateur puisse consulter les modifications pendant qu'elles sont apportées et annuler l'opération si nécessaire.

Vous devez toutefois savoir que le magasin de modèles n'est pas thread-safe. Vous devez toujours utiliser le thread d'interface utilisateur pour effectuer les mises à jour et, si possible, empêcher l'utilisateur d'apporter des modifications pendant que l'opération d'arrière-plan est en cours. Pour obtenir un exemple, consultez Comment : mettre à jour un modèle UML à partir d'un thread d'arrière-plan.

Exécution de la commande de menu

À des fins de test, exécutez votre commande en mode débogage.

Pour tester la commande de menu

  1. Appuyez sur F5, ou dans le menu Déboguer, cliquez sur Démarrer le débogage.

    Une instance expérimentale de Visual Studio démarre alors.

    Résolution des problèmes : Si un nouveau projet Visual Studio ne démarre pas :

    • Si vous avez plusieurs projets, assurez-vous que le projet VSIX est défini comme projet de démarrage de la solution.

    • Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet de démarrage ou l'unique projet, puis cliquez sur Propriétés. Dans l'éditeur de propriétés du projet, cliquez sur l'onglet Déboguer. Assurez-vous que la chaîne présente dans le champ Démarrer le programme externe correspond au chemin d'accès complet de Visual Studio, généralement :

      C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe

  2. Dans l'instance expérimentale de Visual Studio, ouvrez ou créez un projet de modélisation, puis ouvrez ou créez un diagramme de modélisation. Utilisez un diagramme qui appartient à l'un des types répertoriés dans les attributs de la classe de votre commande de menu.

  3. Cliquez avec le bouton droit sur le diagramme. Votre commande doit s'afficher dans le menu.

    Dépannage : si la commande ne s'affiche pas dans le menu, vérifiez que :

    • le projet de commande de menu est répertorié en tant que composant MEF dans la liste Contenu de source.extensions.manifest dans le projet VSIX ;

    • les paramètres des attributs Import et Export sont valides ;

    • la méthode QueryStatus n'affecte pas false aux champs command.Enabled ou Visible ;

    • Le type de diagramme de modèle que vous utilisez (classe UML, séquence, etc.) est représenté comme l'un des attributs de classe ([ClassDesignerExtension], [SequenceDesignerExtension], etc.) de la commande de menu.

Installation et désinstallation d'une extension

Vous pouvez installer une extension Visual Studio sur votre propre ordinateur et sur d'autres.

Pour installer une extension

  1. Sur votre ordinateur, recherchez le fichier .vsix qui a été généré par votre projet VSIX.

    1. Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le projet VSIX et cliquez sur Ouvrir le dossier dans l'Explorateur Windows.

    2. Localisez le fichier bin\*\VotreProjet.vsix.

  2. Copiez le fichier .vsix sur l'ordinateur cible sur lequel vous souhaitez installer l'extension. Il peut s'agir de votre propre ordinateur ou d'un autre.

    L'ordinateur cible doit disposer de l'une des éditions de Visual Studio que vous avez spécifiées dans source.extension.vsixmanifest.

  3. Sur l'ordinateur cible, double-cliquez sur le fichier .vsix.

    Le Programme d'installation des extensions Visual Studio ouvre et installe l'extension.

  4. Démarrez ou redémarrez Visual Studio.

Pour désinstaller une extension

  1. Dans le menu Outils, cliquez sur Gestionnaire d'extensions.

  2. Développez Extensions installées.

  3. Sélectionnez l'extension, puis cliquez sur Désinstaller.

Exceptionnellement, une extension défaillante ne parvient pas à se charger et crée un rapport dans la fenêtre d'erreur, mais ne s'affiche pas dans le gestionnaire d'extensions. Dans ce cas, vous pouvez supprimer l'extension en supprimant le fichier de :

%LocalAppData%\Local\Microsoft\VisualStudio\10.0\Extensions

Exemple

L'exemple suivant affiche le code d'une commande de menu qui échangera les noms de deux éléments d'un diagramme de classes. Ce code doit être généré dans un projet d'extension Visual Studio et installé comme décrit dans les sections précédentes.

using System.Collections.Generic; // for IEnumerable
using System.ComponentModel.Composition;
  // for [Import], [Export]
using System.Linq; // for IEnumerable extensions
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
  // for IDiagramContext
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
  // for designer extension attributes
using Microsoft.VisualStudio.Modeling.Diagrams;
  // for ShapeElement
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
  // for IGestureExtension, ICommandExtension, ILinkedUndoContext
using Microsoft.VisualStudio.Uml.Classes;
  // for class diagrams, packages

/// <summary>
/// Extension to swap names of classes in a class diagram.
/// </summary>
namespace SwapClassNames
{
  // Declare the class as an MEF component:
  [Export(typeof(ICommandExtension))]
  [ClassDesignerExtension]
  // Add more ExportMetadata attributes to make
  // the command appear on diagrams of other types.
  public class NameSwapper : ICommandExtension
  {
  // MEF required interfaces:
  [Import]
  public IDiagramContext Context { get; set; }
  [Import]
  public ILinkedUndoContext LinkedUndoContext { get; set; }

  /// <summary>
  /// Swap the names of the currently selected elements.
  /// </summary>
  /// <param name="command"></param>
  public void Execute(IMenuCommand command)
  {
    // Get selected shapes that are IClassifiers -
    // IClasses, IInterfaces, IEnumerators.
    var selectedShapes = Context.CurrentDiagram
     .GetSelectedShapes<IClassifier>();
    if (selectedShapes.Count() < 2) return;

    // Get model elements displayed by shapes.
    IClassifier firstElement = selectedShapes.First().Element;
    IClassifier lastElement = selectedShapes.Last().Element;

    // Do the swap in a transaction so that user
    // cannot undo one change without the other.
    using (ILinkedUndoTransaction transaction =
    LinkedUndoContext.BeginTransaction("Swap names"))
    {
    string firstName = firstElement.Name;
    firstElement.Name = lastElement.Name;
    lastElement.Name = firstName;
    transaction.Commit();
    }
  }

  /// <summary>
  /// Called by Visual Studio to determine whether
  /// menu item should be visible and enabled.
  /// </summary>
  public void QueryStatus(IMenuCommand command)
  { 
    int selectedClassifiers = Context.CurrentDiagram
     .GetSelectedShapes<IClassifier>().Count();
    command.Visible = selectedClassifiers > 0;
    command.Enabled = selectedClassifiers == 2;
  }

  /// <summary>
  /// Name of the menu command.
  /// </summary>
  public string Text
  {
    get { return "Swap Names"; }
  }
  }

}

Voir aussi

Autres ressources

Comment : définir et installer une extension de modélisation

Extension de modèles et de diagrammes UML

Comment : définir un gestionnaire déposer et double-cliquer sur un diagramme de modélisation

Comment : définir un élément de boîte à outils de modélisation personnalisé

Comment : définir des contraintes de validation pour les modèles UML

Comment : modifier des diagrammes de séquence à l'aide de l'API UML

Programmation à l'aide de l'API UML

Exemple : Commande pour aligner des formes sur un diagramme UML (page éventuellement en anglais)