Partager via


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

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

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.

Voici le variant :

Pour créer une commande de menu à une bibliothèque de classes séparée (DLL) projet

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

    1. Dans le menu Fichier , choisissez Nouveau, Projet.

    2. Sous Modèles installés, Visual C# activez ou Visual Basic.Dans la colonne centrale, choisissez 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.11.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.11.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 Extension des diagrammes de couche.

    Définissez des commandes sur un diagramme de couche.

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

    [!REMARQUE]

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

    Si vous définissez plusieurs commandes, ils apparaissent dans le menu dans l'ordre alphabétique des noms de classe.

    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]
    
      // All menu commands must export ICommandExtension:
      [Export (typeof(ICommandExtension))]
      // CHANGE class name – determines order of appearance on menu:
      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 à 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 Explorateur de solutions, dans le menu contextuel de la solution, choisissez Ajouter, Nouveau projet.

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

  3. Dans l'explorateur de solutions, dans le menu contextuel du projet VSIX, choisissez Définir comme projet de démarrage.

  4. Ouvrez source.extension.vsixmanifest.

    1. Sous l'onglet métadonnées , affectez un nom pour le projet VSIX.

    2. Sous l'onglet installez les cibles , affectez Visual Studio ultimate et premium comme cibles.

    3. Sous l'onglet Ressources , choisissez Nouveau, et dans la boîte de dialogue, affectez :

      Type = Composant MEF

      Source = un projet dans la solution actuelle

      Projet = Votre projet de Bibliothèque de classes

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é.

 

Ee329481.collapse_all(fr-fr,VS.110).gifAccè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>()) {...}

Ee329481.collapse_all(fr-fr,VS.110).gifAccè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.

Ee329481.collapse_all(fr-fr,VS.110).gifUtilisation 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 F5, ou dans le menu Déboguer , choisissez 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, dans le menu contextuel du démarrage ou uniquement du projet, choisissez Propriétés.Dans l'éditeur de propriétés du projet, sélectionnez Déboguer tableau.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 11.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. Ouvrez le menu contextuel 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 l'onglet Ressources dans 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 Explorateur de solutions, dans le menu contextuel du projet VSIX, choisissez 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, ouvrez le fichier d' .vsix , par exemple en double-cliquant dessus.

    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 , choisissez gestionnaire d'extensions.

  2. Développez Extensions installées.

  3. Sélectionnez l'extension, puis choisissez 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\11.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

Concepts

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

Extension de modèles et de diagrammes UML

Comment : définir un gestionnaire de mouvements 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

Autres ressources

Exemple : Commande d'alignement de formes sur un diagramme UML