Partilhar via


Como definir um comando de menu em um diagrama de modelagem

No Visual Studio Ultimate, você pode definir itens de menu adicionais nos menus de atalho de um diagrama de UML. Você pode controlar se o comando de menu aparece e está habilitado no menu de atalho de qualquer elemento no diagrama, e pode escrever código que é executado quando o usuário escolhe o item de menu. Você pode empacotar essas extensões em uma Extensão de Integração do Visual Studio (VSIX) e distribuí-la a outros usuários do Visual Studio.

Requisitos

Definindo o comando de menu

Para criar um comando de menu para um designer UML, você deve criar uma classe que define o comportamento do comando e inserir a classe em um VSIX (Extensão de Integração do Visual Studio). O VSIX atua como um contêiner que pode instalar o comando. Há dois métodos alternativos de definição de um comando de menu:

  • Crie um comando de menu em seu próprio VSIX usando um modelo de projeto. Esse é o método mais rápido. Use-o se você não deseja combinar seus comandos de menu com outros tipos de extensão, como extensões de validação, itens da caixa de ferramentas personalizada ou manipuladores de gesto.

  • Criar comando de menu separado e projetos de VSIX. Use este método se você desejar combinar vários tipos de extensões no mesmo VSIX. Por exemplo, se seu comando de menu esperar que o modelo observe as restrições específicas, você poderá inseri-lo no mesmo VSIX que um método de validação.

Para criar um comando de menu em seu próprio VSIX

  1. Na caixa de diálogo Novo Projeto, em Modelando Projetos, selecione Extensão de Comando.

  2. Abra o arquivo .cs no novo projeto e modifique a classe CommandExtension para implementar o comando.

    Para obter mais informações, consulte Implementando o comando de menu.

  3. Você pode adicionar outros comandos a este projeto definindo novas classes.

  4. Teste o comando de menu pressionando F5. Para obter mais informações, consulte Executando o comando de menu.

  5. Instale o comando de menu em outro computador copiando o arquivo bin\*\*.vsix que é compilado pelo seu projeto. Para obter mais informações, consulte Instalando o comando de menu.

Veja o procedimento alternativo:

Para criar um comando de menu em um projeto de biblioteca de classe separada (DLL)

  1. Crie um projeto de biblioteca de classes, em uma solução nova ou existente do Visual Studio.

    1. No menu Arquivo, escolha Novo Projeto.

    2. Em Modelos Instalados, selecione Visual C# ou Visual Basic. Na coluna do meio, escolha Biblioteca de Classes.

    3. Defina a Solução para indicar se você deseja criar uma nova solução ou adicionar um componente a uma solução VSIX que você já abriu.

    4. Defina o nome e o local do projeto e clique em OK.

  2. Adicione as seguintes referências ao projeto.

    Referência

    O que isso permite que você faça

    System.ComponentModel.Composition

    Define componentes usando Managed Extensibility Framework (MEF).

    Microsoft.VisualStudio.Uml.Interfaces

    Leia e altere as propriedades de elementos de modelo.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility

    Crie elementos de modelo, modifique as formas em diagramas.

    Microsoft.VisualStudio.Modeling.Sdk.12.0

    Defina os manipuladores de evento do modelo.

    Encapsular a série de alterações no modelo. Para obter mais informações, consulte Como vincular atualizações de modelo usando transações.

    Microsoft.VisualStudio.Modeling.Sdk.Diagrams.12.0

    (nem sempre necessário)

    Acesse os elementos adicionais de diagrama para manipuladores de gesto.

    Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer

    Necessário somente para comandos em diagramas de camada. Para obter mais informações, consulte Estendendo diagramas de camada.

    Defina comandos em um diagrama de camada.

  3. Adicione um arquivo de classe ao projeto e defina seu conteúdo para o código a seguir.

    Dica

    Altere o namespace, o nome da classe e o valor retornado por Text de acordo com sua preferência.

    Se você definir mais comandos, eles aparecerão no menu em ordem alfabética dos nomes 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>()) 
          { }
        }
      }
    }
    

    Para obter mais informações sobre o que colocar nos métodos, consulte Implementando o comando de menu.

Você deve adicionar o comando de menu a um projeto VSIX, que atua como um contêiner para instalação do comando. Se você desejar, você pode incluir outros componentes no mesmo VSIX.

Para adicionar um comando de menu a um projeto VSIX

  1. Você não precisará deste procedimento se tiver criado o comando de menu com seu próprio VSIX.

  2. Crie um projeto de VSIX, a menos que sua solução já tenha um.

    1. No Gerenciador de Soluções, no menu de atalho da solução, escolha Adicionar, Novo Projeto.

    2. Em Modelos Instalados, expanda Visual C# ou Visual Basic e escolha Extensibilidade. Na coluna do meio, escolha Projeto VSIX.

  3. No Gerenciador de Soluções, no menu de atalho do projeto VSIX, selecione Definir como projeto de inicialização.

  4. Abra source.extension.vsixmanifest.

    1. Na guia Metadados, defina um nome para o VSIX.

    2. Na guia Instalar Destinos, defina o Visual Studio Ultimate e Premium como os destinos.

    3. Na guia Ativos, escolha Novo e, na caixa de diálogo, defina:

      Digite = Componente MEF

      Origem = Um projeto na solução atual

      Projeto = Your class library project

Implementando o comando de menu

A classe do comando de menu implementa os métodos necessários para ICommandExtension.

string Text { get; }

Retornar o rótulo do item de menu.

void QueryStatus(IMenuCommand command);

Chamado quando o usuário clica com o botão direito do mouse no diagrama.

Esse método não deve alterar o modelo.

Use DiagramContext.CurrentDiagram.SelectedShapes para determinar se você deseja que o comando apareça e seja habilitado.

Definir:

  • command.Visible para true se o comando tiver que aparecer no menu quando o usuário clica com o botão direito do mouse no diagrama

  • command.Enabled para true se o usuário for capaz de clicar no comando no menu

  • command.Text para definir dinamicamente o rótulo de menu

void Execute (IMenuCommand command);

Chamado quando o usuário clica no item de menu, se estiver visível e habilitado.

 

Acessando o modelo no código

Incluindo a seguinte declaração na sua classe de comando de menu:

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

...

A declaração de IDiagramContext permite que você escreva códigos em seus métodos que acessam o diagrama, a seleção atual e o modelo:

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>()) {...}

Os elementos do modelo de UML estão todos disponíveis por meio da API. Na seleção atual ou raiz do modelo, você pode acessar todos os elementos restantes. Para obter mais informações, consulte Como: navegar no modelo UML e Programando com a API UML.

Se você estiver lidando um diagrama de sequência, consulte também Como editar diagramas de sequência usando a API UML.

A API também permite que você altere as propriedades de elementos, exclua elementos e relações e crie novos elementos e relações.

Por padrão, cada alteração feita no seu método de execução será executada em uma transação separada. O usuário poderá desfazer separadamente cada alteração. Se você desejar agrupar as alterações em uma única transação, use ILinkedUndoTransaction conforme descrito em Como vincular atualizações de modelo usando transações.

Use o Thread de interface de usuário para atualizações

Em alguns casos, pode ser útil fazer atualizações no modelo a partir de um segmento de plano de fundo. Por exemplo, se o comando carregar dados de um recurso lento, você poderá executar o carregamento em um segmento de plano de fundo de modo que o usuário possa ver as alterações quando elas estiverem em andamento, e cancelar a operação se necessário.

Entretanto, você deve estar ciente que o armazenamento de modelo não tem segurança de segmentos. Você sempre deve usar o segmento de (UI) de interface de usuário para realizar atualizações, e se é possível, impede que o usuário faça edições quando a operação de plano de fundo está em andamento. Para ver um exemplo, consulte Como atualizar um modelo UM a partir de um thread em segundo plano.

Executando o comando de menu

Para fins de teste, execute o comando em modo de depuração.

Para testar o comando de menu

  1. Pressione F5 ou, no menu Depurar, escolha Iniciar Depuração.

    Uma instância experimental do Visual Studio é iniciada.

    Solução de problemas: se um novo Visual Studio não for iniciado:

    • Se você tiver mais de um projeto, certifique-se que o projeto de VSIX seja definido como projeto de inicialização da solução.

    • No Gerenciador de Soluções, no menu de atalho da inicialização ou somente projeto, escolha Propriedades. No editor de propriedades de projeto, selecione a guia Depurar. Certifique-se de que a cadeia de caracteres no campo de Iniciar programa externo seja o nome do caminho completo de Visual Studio, normalmente:

      C:\Arquivos de Programas\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe

  2. No Visual Studio experimental, abra ou crie um projeto de modelagem e abra ou crie um diagrama de modelagem. Use um diagrama que pertence a um dos tipos que estão listados nos atributos de sua classe de comando de menu.

  3. Abra o menu de atalho em qualquer lugar no diagrama. Seu comando deve aparecer no menu.

    Solução de problemas: se o comando não aparecer no menu, verifique se:

    • O projeto do comando de menu está listado como um componente MEF na guia Ativos em source.extensions.manifest no projeto VSIX.

    • Os parâmetros dos atributos Import e Export são válidos.

    • O método QueryStatus não está definindo os campos command.Enabled ou Visible como false.

    • O tipo de diagrama modelo que você está usando (classe UML, sequência, etc.) é listado como um dos atributos da classe de comando de menu [ClassDesignerExtension], [SequenceDesignerExtension] e assim por diante.

Instalando e desinstalando uma extensão

Você pode instalar uma extensão de Visual Studio no seu próprio computador e em outros computadores.

Para instalar uma extensão

  1. No seu computador, localize o arquivo .vsix criado pelo seu projeto VSIX.

    1. No Gerenciador de Soluções, no menu de atalho do projeto de VSIX, escolha Abrir pasta no Windows Explorer.

    2. Localize o arquivo bin\*\YourProject.vsix

  2. Copie o arquivo de .vsix para o computador de destino em que você deseja instalar a extensão. Pode ser o seu próprio computador ou algum outro.

    O computador de destino deve ter uma das edições de Visual Studio que você especificou em source.extension.vsixmanifest.

  3. No computador de destino, abra o arquivo .vsix, por exemplo, clicando duas vezes nele.

    Instalador de Extensão do Visual Studio abre e instala a extensão.

  4. Inicie ou reinicie o Visual Studio.

Para desinstalar uma extensão

  1. No menu de Ferramentas, escolha Gerenciador de Extensões.

  2. Expanda Extensões Instaladas.

  3. Selecione a extensão e escolha Desinstalar.

Raramente, uma extensão defeituosa falha ao ser carregada e cria um relatório na janela de erros, mas não aparece no Gerenciador de Extensões. Nesse caso, você pode remover a extensão excluindo o arquivo de:

%LocalAppData%\Local\Microsoft\VisualStudio\12.0\Extensions

Exemplo

O exemplo a seguir mostra o código para um comando de menu que fará intercâmbio entre os nomes de dois elementos em um diagrama de classes. Esse código deve ser criado em um projeto de Extensão do Visual Studio e instalado conforme descrito nas seções anteriores.

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

}

Consulte também

Conceitos

Como definir e instalar uma extensão de modelagem

Estendendo modelos e diagramas UML

Como definir um manipulador de gesto em um diagrama de modelagem

Como definir um item da caixa de ferramentas de modelagem personalizado

Como definir restrições de validação para modelos UML

Como editar diagramas de sequência usando a API UML

Programando com a API UML

Outros recursos

Exemplo: Comando para alinhar formas em um diagrama Diagrama UML