Procedura: definire un comando di menu in un diagramma di modellazione

In Visual Studio ultimate, è possibile definire voci di menu aggiuntive sui menu di scelta rapida di un diagramma UML.È possibile controllare se il comando di menu viene visualizzato e abilitato sul menu di scelta rapida di un qualsiasi elemento del diagramma ed è possibile scrivere codice che venga eseguito quando l'utente seleziona la voce di menu.È possibile comprimere queste estensioni in un pacchetto Visual Studio Integration Extension (VSIX), e distribuirlo ad altri utenti di Visual Studio(la pagina potrebbe essere in inglese).

Requisiti

Definizione del comando di menu

Per creare un comando di menu per una finestra di progettazione UML, è necessario creare una classe che definisce il comportamento del comando e incorporarla in un progetto VSIX (Visual Studio Integration Extension).Il progetto VSIX funge da contenitore per l'installazione del comando.Esistono due metodi alternativi per definire un comando di menu:

  • Creazione di un comando di menu in un progetto VSIX distinto mediante un modello di progetto. Si tratta del metodo più rapido.Utilizzarlo se non si desidera combinare i comandi di menu con altri tipi di estensione quali estensioni della convalida, elementi della casella degli strumenti personalizzati o gestori movimenti.

  • Creazione di progetti di comando di menu e progetti VSIX distinti. Utilizzare questo metodo se si desidera combinare più tipi di estensione nello stesso progetto VSIX.Ad esempio, se per il comando di menu è previsto che il modello osservi vincoli specifici, è possibile incorporarlo nello stesso progetto VSIX come un metodo di convalida.

Per creare un comando di menu in un progetto VSIX distinto

  1. Nella finestra di dialogo Nuovo progetto, sotto Progetti di modello fare clic su Estensione di comando.

  2. Aprire il file con estensione .cs nel nuovo progetto e modificare la classe CommandExtension per implementare il comando.

    Per ulteriori informazioni, vedere Implementazione del comando di menu.

  3. È possibile aggiungere ulteriori comandi al progetto definendo nuove classi.

  4. Testare il comando di menu premendo F5.Per ulteriori informazioni, vedere Esecuzione del comando di menu.

  5. Installare il comando di menu in un altro computer copiando il file bin\*\*.vsix compilato dal progetto.Per ulteriori informazioni, vedere Installazione del comando di menu.

Di seguito è riportata la procedura alternativa:

Per creare un comando di menu in un progetto Libreria di classi (DLL) distinto

  1. Creare un progetto Libreria di classi, in una nuova soluzione Visual Studio o in una soluzione esistente.

    1. Dal menu File, scegliere Nuovo, Progetto.

    2. In Modelli installati selezionare Visual C# o Visual Basic.Nella colonna centrale scegliere Libreria di classi.

    3. Impostare Soluzione per indicare se si desidera creare una nuova soluzione o aggiungere un componente a una soluzione VSIX già aperta.

    4. Impostare nome e percorso per il progetto, quindi fare clic su OK.

  2. Aggiungere i riferimenti seguenti al progetto.

    Riferimento

    Operazioni consentite

    System.ComponentModel.Composition

    Definire i componenti utilizzando il framework di estensibilità gestita (MEF, Managed Extensibility Framework) (la pagina potrebbe essere in inglese).

    Microsoft.VisualStudio.Uml.Interfaces

    Leggere e modificare le proprietà degli elementi del modello.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Creare elementi del modello, modificare forme nei diagrammi.

    Microsoft.VisualStudio.Modeling.Sdk.11.0

    Definire i gestori eventi del modello.

    Incapsulare serie di modifiche nel modello.Per ulteriori informazioni, vedere Procedura: collegare aggiornamenti di modelli tramite transazioni.

    Microsoft.VisualStudio.Modeling.Sdk.Diagrams.11.0

    (non sempre necessario)

    Accedere a elementi del diagramma aggiuntivi per i gestori movimenti.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer

    Richiesto solo per i comandi nei diagrammi livello.Per ulteriori informazioni, vedere Estensione dei diagrammi livello.

    Definire comandi in un diagramma livello.

  3. Aggiungere un file di classe al progetto e impostarne il contenuto sul codice seguente.

    [!NOTA]

    Cambiare lo spazio dei nomi, il nome della classe e il valore restituito da Text in base alle proprie preferenze.

    Se si definiscono più controlli, vengono visualizzati in ordine alfabetico a seconda dei nomi della 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>()) 
          { }
        }
      }
    }
    

    Per ulteriori informazioni su cosa inserire nei metodi, vedere Implementazione del comando di menu.

È necessario aggiungere il comando di menu a un progetto VSIX, che fungerà da contenitore per l'installazione del comando.Se si desidera, è possibile includere altri componenti nello stesso progetto VSIX.

Per aggiungere un comando distinto di menu distinto a un progetto VSIX

  1. Questa routine non è necessaria se si è creato il comando di menu con un progetto VSIX distinto.

  2. Creare un progetto VSIX, a meno che la soluzione non ne includa già uno.

    1. In Esplora soluzioni, scegliere dal menu di scelta rapida della soluzione Aggiungi, Nuovo progetto.

    2. In Modelli installati espandere Visual Basic o Visual C#, quindi scegliere Extensibilità.Nella colonna centrale scegliere Progetto VSIX.

  3. In Esplora soluzioni, dal menu di scelta rapida del progetto VSIX, scegliere Imposta come progetto di avvio.

  4. Aprire source.extension.vsixmanifest.

    1. Nella scheda metadati, impostare un nome per il progetto VSIX.

    2. Nella scheda Installa destinazioni, impostare Visual Studio Premium e Ultimate come destinazioni.

    3. Nella scheda Asset, scegliere Nuovoe nella finestra di dialogo impostare:

      Tipo = Componente MEF

      Origine = Progetto nella soluzione corrente

      Progetto = Il progetto Libreria di classi

Implementazione del comando di menu

La classe del comando di menu implementa i metodi necessari per ICommandExtension.

string Text { get; }

Restituisce l'etichetta della voce di menu.

void QueryStatus(IMenuCommand command);

Chiamato quando l'utente fa clic con il pulsante destro del mouse nel diagramma.

Questo metodo non deve modificare il modello.

Utilizzare DiagramContext.CurrentDiagram.SelectedShapes per determinare se si desidera che il comando venga visualizzato e abilitato.

Impostare:

  • command.Visible su true se il comando deve essere visualizzato nel menu quando l'utente fa clic con il pulsante destro del mouse nel diagramma

  • command.Enabled su true se l'utente può fare clic sul comando nel menu

  • command.Text per impostare l'etichetta del menu in modo dinamico

void Execute (IMenuCommand command);

Chiamato quando l'utente fa clic sulla voce di menu, se visibile e abilitato.

 

Ee329481.collapse_all(it-it,VS.110).gifAccesso al modello nel codice

Includendo la dichiarazione seguente nella classe del comando di menu:

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

...

La dichiarazione di IDiagramContext consente di scrivere codice nei metodi che sia in grado di accedere al diagramma, alla selezione corrente e al modello:

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(it-it,VS.110).gifSpostamento e aggiornamento del modello

Gli elementi del modello UML sono tutti disponibili tramite l'API.Dalla selezione corrente o dalla radice del modello, è possibile accedere a tutti gli altri elementi.Per ulteriori informazioni, vedere Procedura: esplorare il modello UML e Programmazione con l'API UML.

Se si utilizza un diagramma di sequenza, vedere anche Procedura: modificare i diagrammi di sequenza tramite l'API UML.

L'API consente inoltre di modificare le proprietà di elementi, eliminare elementi e relazioni e creare nuovi elementi e relazioni.

Per impostazione predefinita, ogni modifica apportata nel metodo Execute verrà eseguita in una transazione separata.L'utente potrà annullare ogni modifica separatamente.Se si desidera raggruppare le modifiche in una sola transazione, utilizzare un oggetto ILinkedUndoTransaction come descritto in Procedura: collegare aggiornamenti di modelli tramite transazioni.

Ee329481.collapse_all(it-it,VS.110).gifUtilizzare il thread dell'interfaccia utente per gli aggiornamenti

Talvolta può essere utile apportare aggiornamenti al modello da un thread in background.Se, ad esempio, tramite il comando vengono caricati dati da una risorsa lenta, è possibile eseguire il caricamento in un thread in background, in modo che l'utente possa visualizzare le modifiche mentre sono in corso e annullare l'operazione, se necessario.

È tuttavia necessario tenere presente che l'archivio del modello non è thread-safe.È necessario utilizzare sempre il thread dell'interfaccia utente per eseguire aggiornamenti e, se possibile, impedire all'utente di apportare modifiche mentre è in corso l'operazione in background.Per un esempio, vedere Procedura: aggiornare un modello UML da un thread in background.

Esecuzione del comando di menu

A scopo di test, eseguire il comando in modalità di debug.

Per testare il comando di menu

  1. Premere F5, o dal menu Debug scegliere Inizia debugging.

    Verrà avviata un'istanza sperimentale di Visual Studio.

    Risoluzione dei problemi. Se non viene avviata una nuova istanza di Visual Studio:

    • Se si dispone di più progetti, verificare che il progetto VSIX sia impostato come progetto di avvio della soluzione.

    • In Esplora soluzioni, dal menu di scelta rapida dell'avvio o solamente dal progetto, scegliere Proprietà.Scegliere la scheda Debug nell'editor delle proprietà del progetto.Assicurarsi che la stringa nel campo Avvia programma esterno sia il percorso completo di Visual Studio, in genere:

      C:\Programmi\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe

  2. Nell'istanza sperimentale di Visual Studio aprire o creare un progetto di modello e un diagramma di modellazione.Utilizzare un diagramma appartenente a uno dei tipi elencati negli attributi della classe del comando di menu.

  3. Aprire il menu di scelta rapida in un punto qualsiasi del diagramma.Il comando dovrebbe venire visualizzato nel menu.

    Risoluzione dei problemi: se il comando non viene visualizzato nel menu, verificare quanto indicato di seguito:

    • Il progetto di comando di menu è elencato come componente MEF nella scheda Assetti in source.extensions.manifest nel progetto VSIX.

    • I parametri degli attributi Import ed Export sono validi.

    • Tramite il metodo QueryStatus i campi command.Enabled e Visible non vengono impostati su false.

    • Il tipo di diagramma di modello utilizzato (classi UML, sequenza e così via) viene elencato come uno degli attributi della classe del comando di menu [ClassDesignerExtension], [SequenceDesignerExtension] e così via.

Installazione e disinstallazione di un'estensione

È possibile installare un'estensione di Visual Studio sia nel computer in uso che in altri computer.

Per installare un'estensione

  1. Nel computer trovare il file .vsix compilato dal progetto VSIX.

    1. In Esplora soluzioni, dal menu di scelta rapida del progetto VSIX scegliere Apri cartella in Esplora risorse.

    2. Individuare il file bin\*\Progetto.vsix

  2. Copiare il file .vsix nel computer di destinazione in cui si desidera installare l'estensione.Si può trattare del computer in uso o di un altro computer.

    Nel computer di destinazione deve essere presente una delle versioni di Visual Studio specificata in source.extension.vsixmanifest.

  3. Nel computer di destinazione, aprire il file .vsix, ad esempio facendo doppio clic su.

    Verrà visualizzato Visual Studio Extension Installer e verrà installata l'estensione.

  4. Avviare o riavviare Visual Studio.

Per disinstallare un'estensione

  1. Scegliere Gestione estensioni dal menu Strumenti.

  2. Espandere Estensioni installate.

  3. Selezionare l'estensione, quindi fare clic su Disinstalla.

Raramente, può verificarsi che un'estensione errata non venga caricata creando un rapporto nella finestra di errore. Tale estensione non viene però visualizzata in Gestione estensioni.In tal caso, è possibile rimuovere l'estensione eliminando il file da:

%LocalAppData%\Local\Microsoft\VisualStudio\11.0\Extensions

Esempio

Nell'esempio seguente viene illustrato il codice per un comando di menu che interscambierà i nomi di due elementi in un diagramma classi.Questo codice deve essere incorporato in un progetto Visual Studio Extension e installato come descritto nelle sezioni precedenti.

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"; }
  }
  }

}

Vedere anche

Concetti

Procedura: definire e installare un'estensione di modellazione

Estensione di modelli e diagrammi UML

Procedura: definire un gestore movimenti in un diagramma di modellazione

Procedura: definire un elemento personalizzato della Casella degli strumenti di modellazione

Procedura: definire vincoli di convalida per i modelli UML

Procedura: modificare i diagrammi di sequenza tramite l'API UML

Programmazione con l'API UML

Altre risorse

Esempio di comando per allineare le forme in un diagramma UML