Como: Exibir um modelo em diagramas

No código de programa para uma extensão para Visual Studio Ultimate, você pode controlar como os elementos de modelo são exibidos em diagramas.

  • Neste tópico:

    • Para exibir um elemento em um diagrama

    • Acessando as formas que representam um elemento

    • Movendo e redimensionando formas

    • Para remover uma forma de um diagrama.

    • Abrindo e criação de diagramas

    • Exemplo: Comando para alinhar formas

Para exibir um elemento em um diagrama

Quando você cria um elemento como um caso de uso ou uma ação, o usuário pode ver no Gerenciador de modelos UML, mas sempre automaticamente não aparece em um diagrama. Em alguns casos, você deve escrever código para exibi-la. A tabela a seguir resume as alternativas.

 

Tipo de elemento

Por exemplo

Para exibir isso, seu código deve

Classificador

Class

Component

Actor

Use Case

Crie formas associadas em diagramas especificados. Você pode criar qualquer número de formas para cada classificador.

diagram.Display<modelElementType>

(modelElement, parentShape,

xPosition , yPosition);

Definir parentShape para null de uma forma de nível superior do diagrama.

Para exibir uma forma dentro de outro:

IShape<IUseCase> usecaseShape =

useCaseDiagram.Display

(useCase,

subsystemShape,

subsystemShape.XPosition + 5,

subsystemShape.YPosition + 5);

ObservaçãoObservação
Se você executar o vídeo dentro de um ILinkedUndo a transação, às vezes, o método retornará não IShape.Mas a forma é criada corretamente e está acessível usando oIElement.Shapes().

Filho do classificador

Atributo, operação,

Parte, a porta

Automático - nenhum código necessário.

Ele é exibido como parte do pai.

Comportamento

Interação (seqüência)

Atividade

Vincule o comportamento a um diagrama apropriado.

Cada comportamento pode ser vinculado a no máximo um diagrama de cada vez.

Por exemplo:

sequenceDiagram.Bind(interaction);

activityDiagram.Bind(activity);

Filho do comportamento

Linhas de vida, mensagens, ações, nós de objeto

Automático - nenhum código necessário.

Ela é exibida se o pai estiver acoplado a um diagrama.

Relacionamento

Associação, generalização, fluxo, dependência

Automático - nenhum código necessário.

Ele é exibido em cada diagrama em que ambas as extremidades são exibidas.

 

Acessando as formas que representam um elemento

A forma que representa um elemento pertence aos tipos:

IShape

IShape<ElementType>

onde ElementType é um tipo de elemento de modelo, como IClass ou IUseCase.

anElement.Shapes ()

Todos os IShapes que representam esse elemento em diagramas abertos.

anElement.Shapes(aDiagram)

Todos os IShapes que representam esse elemento em um diagrama específico.

anIShape.GetElement()

O IElement que representa a forma. Normalmente, você poderia lançá-lo para uma subclasse de IElement.

anIShape.Diagram

O IDiagram que contém a forma.

anIShape.ParentShape

A forma que contém anIShape. Por exemplo, uma forma de porta está contida dentro de uma forma de componente.

anIShape.ChildShapes

As formas contidas em um IShape ou IDiagram.

anIShape.GetChildShapes<IUseCase>()

As formas contidas dentro de um IShape ou IDiagram que representam os elementos do tipo especificado, como IUseCase.

IShape iShape = ...;

IShape<IClass> classShape = iShape.ToIShape<IClass>();

IClass aClass = classShape.Element;

Converter um genérico IShape para um com rigidez de tipos IShape<IElement>.

IShape<IClassifier> classifierShape;

IShape<IUseCase> usecaseShape =

classifierShape.ToIShape<IUseCase>();

Converta uma forma de uma forma com parâmetros de tipo para outro.

Movendo e redimensionando formas

anIShape.Move(x, y, [width], [height])

Mover ou redimensionar uma forma.

IDiagram.EnsureVisible( IEnumerable<IShape> shapes, bool zoomToFit = false)

Ative a janela e rolar o diagrama para que todas as formas de determinado fiquem visíveis. As formas devem estar no diagrama. Se zoomToFit for true, o diagrama será dimensionado se necessário para que todas as formas fiquem visíveis.

Por exemplo, consulte a definição de um comando de alinhamento.

Para remover uma forma de um diagrama.

Você pode excluir as formas de alguns tipos de elemento sem excluir o elemento.

Elemento de modelo

Para remover a forma

Um classificador: uma classe, interface, enumeração, ator, caso de uso ou componente

shape.Delete();

Um comportamento: interação ou atividade

Você pode excluir o diagrama do projeto. Use IDiagram.FileName para obter o caminho.

Isso não exclui o comportamento do modelo.

Qualquer outra forma.

Você explicitamente não é possível excluir a outras formas de um diagrama. A forma desaparecerá automaticamente se o elemento é excluído do modelo, ou se a forma pai é removida do diagrama.

Abrindo e criação de diagramas

Para acessar o diagrama de atual do usuário de um comando ou o gesto de extensão

Declare esta propriedade importada em sua classe:

[Import]

IDiagramContext Context { get; set; }

 

Em um método, acesse o diagrama:

IClassDiagram classDiagram =

Context.CurrentDiagram as IClassDiagram;

ObservaçãoObservação

Uma instância de IDiagram (e seus subtipos, como IClassDiagram) só é válido dentro do comando processamento. Não é recomendável manter uma IDiagram o objeto em uma variável que persiste enquanto o controle é retornado ao usuário.

Para obter mais informações, consulte Como: Definir um comando de Menu em um diagrama de modelagem.

Para obter uma lista de diagramas abertos

Uma lista de diagramas que estão atualmente abertos no projeto:

Context.CurrentDiagram.ModelStore.Diagrams()

Para acessar os diagramas em um projeto

O Visual Studio API pode ser usada para abrir e criar projetos de modelagem e diagramas.

Observe a conversão de EnvDTE.ProjectItem para IDiagramContext.

using EnvDTE; // Visual Studio API
...
[Import]
public IServiceProvider ServiceProvider { get; set; }
...
// Get Visual Studio API
DTE dte = ServiceProvider.GetService(typeof(DTE)) as DTE;
// Get current Visual Studio project
Project project = dte.ActiveDocument.ProjectItem.ContainingProject;
// Open and process every diagram in the project.
foreach (ProjectItem item in project.ProjectItems)
{
  // Cast ProjectItem to IDiagramContext
  IDiagramContext context = item as IDiagramContext;
  if (context == null)
  {
     // This is not a diagram file.
     continue;
  }
  // Open the file and give the window the focus.
  if (!item.IsOpen)
  {
      item.Open().Activate();
  }
  // Get the diagram.
  IDiagram diagram = context.CurrentDiagram;
  // Deal with specific diagram types.
  ISequenceDiagram seqDiagram = diagram as ISequenceDiagram;
  if (seqDiagram != null)
  { ... } } }

Instâncias de IDiagram e seus subtipos não são válidos após retornar o controle para Visual Studio.

Você também pode obter o armazenamento de modelo de um Visual Studio projeto:

Project project = ...;
IModelStore modelStore = (project as IModelingProject).Store;

Exemplo: Comando para alinhar formas

O código a seguir implementa um comando de menu Alinha formas ordenadamente. O usuário deve primeiro colocar duas ou mais formas em alinhamento aproximado, vertical ou horizontalmente. Em seguida, o comando Alinhar pode ser usado para alinhar seus centros.

Para disponibilizar o comando, adicione este código para um projeto de comando de menu e, em seguida, implantar a extensão resultante para seus usuários. Para obter mais informações, consulte Como: Definir um comando de Menu em um diagrama de modelagem.

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;

namespace AlignCommand
{
  // Implements a command to align shapes in a UML class diagram.
  // The user first selects shapes that are roughly aligned either vertically or horizontally.
  // This command will straighten them up.

  // Place this file in a menu command extension project.
  // See https://msdn.microsoft.com/library/ee329481.aspx

  [Export(typeof(ICommandExtension))]
  [ClassDesignerExtension] // TODO: Add other diagram types if needed
  class CommandExtension : ICommandExtension
  {
    /// <summary>
    /// See https://msdn.microsoft.com/library/ee329481.aspx
    /// </summary>
    [Import]
    IDiagramContext context { get; set; }

    /// <summary>
    /// Transaction context.
    /// See https://msdn.microsoft.com/library/ee330926.aspx
    /// </summary>
    [Import]
    ILinkedUndoContext linkedUndo { get; set; }

    /// <summary>
    /// Called when the user selects the command.
    /// </summary>
    /// <param name="command"></param>
    public void Execute(IMenuCommand command)
    {
      Align(context.CurrentDiagram.SelectedShapes);
    }

    /// <summary>
    /// Called when the user right-clicks on the diagram.
    /// Determines whether the command is enabled.
    /// </summary>
    /// <param name="command"></param>
    public void QueryStatus(IMenuCommand command)
    {
      IEnumerable<IShape> currentSelection = context.CurrentDiagram.SelectedShapes;
      // Make it visible if there are shapes selected:
      command.Visible = currentSelection.Count() > 0 && !(currentSelection.FirstOrDefault() is IDiagram);

      // Make it enabled if there are two or more shapes that are roughly in line:
      command.Enabled = currentSelection.Count() > 1
        && (HorizontalAlignCenter(currentSelection) > 0.0
        || VerticalAlignCenter(currentSelection) > 0.0);

    }

    /// <summary>
    /// Title of the menu command.
    /// </summary>
    public string Text
    {
      get { return "Align Shapes"; }
    }

    /// <summary>
    /// Find a horizontal line that goes through a list of shapes.
    /// </summary>
    /// <param name="shapes"></param>
    /// <returns></returns>
    private static double HorizontalAlignCenter(IEnumerable<IShape> shapes)
    {
      double Y = -1.0;
      double top = 0.0, bottom = shapes.First().Bottom();
      foreach (IShape shape in shapes)
      {
        top = Math.Max(top, shape.Top());
        bottom = Math.Min(bottom, shape.Bottom());
      }
      if (bottom > top) Y = (bottom + top) / 2.0;
      return Y;
    }

    /// <summary>
    /// Find a vertical line that goes through a list of shapes.
    /// </summary>
    /// <param name="shapes"></param>
    /// <returns></returns>
    private static double VerticalAlignCenter(IEnumerable<IShape> shapes)
    {
      double X = -1.0;
      double left = 0.0, right = shapes.First().Right();
      foreach (IShape shape in shapes)
      {
        left = Math.Max(left, shape.Left());
        right = Math.Min(right, shape.Right());
      }
      if (right > left) X = (right + left) / 2.0;
      return X;
    }

    /// <summary>
    /// Line up those shapes that are roughly aligned.
    /// </summary>
    /// <param name="shapes"></param>
    private void Align(IEnumerable<IShape> shapes)
    {
      if (shapes.Count() > 1)
      {
        // The shapes must all overlap either horizontally or vertically.
        // Find a horizontal line that is covered by all the shapes:
        double Y = HorizontalAlignCenter(shapes);
        if (Y > 0.0) // Negative if they don't overlap.
        {
          // Adjust all the shape positions in one transaction:
          using (ILinkedUndoTransaction t = linkedUndo.BeginTransaction("align"))
          {
            foreach (IShape shape in shapes)
            {
              shape.AlignYCenter(Y);
            }
            t.Commit();
          }
        }
        else
        {
          // Find a vertical line that is covered by all the shapes:
          double X = VerticalAlignCenter(shapes);
          if (X > 0.0) // Negative if they don't overlap.
          {
            // Adjust all the shape positions in one transaction:
            using (ILinkedUndoTransaction t = linkedUndo.BeginTransaction("align"))
            {
              foreach (IShape shape in shapes)
              {
                shape.AlignXCenter(X);
              }
              t.Commit();
            }
          }
        }
      }
    }
  }
  
  /// <summary>
  /// Convenience extensions for IShape.
  /// </summary>
  public static class IShapeExtension
  {
    public static double Bottom(this IShape shape)
    {
      return shape.YPosition + shape.Height;
    }

    public static double Top(this IShape shape)
    {
      return shape.YPosition;
    }

    public static double Left(this IShape shape)
    {
      return shape.XPosition;
    }

    public static double Right(this IShape shape)
    {
      return shape.XPosition + shape.Width;
    }

    public static void AlignYCenter(this IShape shape, double Y)
    {
      shape.Move(shape.XPosition, Y - shape.YCenter());
    }

    public static void AlignXCenter(this IShape shape, double X)
    {
      shape.Move(X - shape.XCenter(), shape.YPosition);
    }

    /// <summary>
    /// We can adjust what bit of the shape we want to be aligned.
    /// The default is the center of the shape.
    /// </summary>
    /// <param name="shape"></param>
    /// <returns></returns>
    public static double YCenter(this IShape shape)
    {
        return shape.Height / 2.0;
    } 
    
    /// <summary>
    /// We can adjust what bit of the shape we want to be aligned.
    /// The default is the center of the shape.
    /// </summary>
    /// <param name="shape"></param>
    /// <returns></returns>
    public static double XCenter(this IShape shape)
    {
        return shape.Width / 2.0;
    }
  }
}

Consulte também

Conceitos

Diagramas e modelos UML estendendo

Como: Navegue de modelo UML

Histórico de alterações

Date

History

Motivo

Março de 2011

Exemplo de alinhamento adicionado.

Comentários do cliente.