Como: exibir um modelo em diagramas
No código de programa para uma extensão do 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: O 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 ele não aparece automaticamente 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 no 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ção
Se você executar o vídeo dentro de um ILinkedUndo transação, o método retorna, às vezes, não IShape.Mas a forma é criada corretamente e está acessível usandoIElement.Shapes().
|
Filho do classificador |
Atributo, operação, Parte, 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 um diagrama de no máximo uma 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 representando 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 Definindo 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 outras formas de um diagrama.A forma desaparece automaticamente se o elemento for 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ção |
---|
Uma instância de IDiagram (e seus subtipos, como IClassDiagram) é válido somente dentro do comando que você está processando.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 abertos no momento no projeto:
Context.CurrentDiagram.ModelStore.Diagrams()
Para acessar os diagramas em um projeto
O Visual Studio API pode ser usada para abrir e criar diagramas e projetos de modelagem.
Observe a projeçã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 controle para Visual Studio.
Você também pode obter o armazenamento de modelo a partir de um Visual Studio projeto:
Project project = ...;
IModelStore modelStore = (project as IModelingProject).Store;
Exemplo: O comando para alinhar formas
O código a seguir implementa um comando de menu que 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, implante a extensão resultante para os 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