Procedura: visualizzare un modello nei diagrammi
Nel codice programma di un'estensione a Visual Studio Ultimate è possibile controllare il modo in cui gli elementi del modello vengono visualizzati nei diagrammi.
In questo argomento:
Per visualizzare un elemento in un diagramma
Accesso alle forme che rappresentano un elemento
Spostamento e ridimensionamento di forme
Per rimuovere una forma da un diagramma
Apertura e creazione di diagrammi
Esempio: comando per allineare forme
Per visualizzare un elemento in un diagramma
Quando si crea un elemento, come ad esempio un caso di utilizzo o un'azione, l'utente può visualizzarlo in Esplora modelli UML, ma non sempre verrà visualizzato automaticamente in un diagramma.In alcuni casi, è necessario scrivere il codice per visualizzarlo.Nella tabella seguente vengono riepilogate le alternative.
Tipo di elemento |
Esempio: |
Istruzioni di codice |
---|---|---|
Classificatore |
Class Component Actor Use Case |
Creare forme associate nei diagrammi specificati.È possibile creare qualsiasi numero di forme per ogni classificatore. diagram.Display<modelElementType> (modelElement, parentShape, xPosition , yPosition); Impostare parentShape su null per una forma al primo livello del diagramma. Per visualizzare una forma all'interno di un'altra: IShape<IUseCase> usecaseShape = useCaseDiagram.Display (useCase, subsystemShape, subsystemShape.XPosition + 5, subsystemShape.YPosition + 5);
Nota
Se si esegue Display in una transazione ILinkedUndo, il metodo talvolta non restituisce IShape.Ma la forma viene creata correttamente ed è accessibile mediante IElement.Shapes().
|
Elemento figlio del classificatore |
Attributo, operazione parte, porta |
Automatico - non è richiesto alcun codice. Viene visualizzato come parte dell'elemento padre. |
Comportamento |
Interazione (sequenza) Attività |
Associare il comportamento a un diagramma appropriato. Ogni comportamento può essere associato al massimo a un diagramma alla volta. Ad esempio: sequenceDiagram.Bind(interaction); activityDiagram.Bind(activity); |
Elemento figlio del comportamento |
Linee di vita, messaggi, azioni, nodi oggetto |
Automatico - non è richiesto alcun codice. Viene visualizzato se l'elemento padre viene associato a un diagramma. |
Relazione |
Associazione, generalizzazione, flusso, dipendenza |
Automatico - non è richiesto alcun codice. Viene visualizzato in ogni diagramma in cui vengono visualizzate entrambe le estremità. |
Accesso alle forme che rappresentano un elemento
La forma che rappresenta un elemento appartiene ai tipi:
IShape
IShape<TipoElemento>
dove TipoElemento è un tipo dell'elemento del modello, ad esempio IClass o IUseCase.
anElement.Shapes () |
Tutti i tipi IShapes che rappresentano questo elemento in diagrammi aperti. |
anElement.Shapes(aDiagram) |
Tutti i tipi IShapes che rappresentano questo elemento in un diagramma specifico. |
anIShape.GetElement() |
Il tipo IElement rappresentato dalla forma.In genere lo si sottopone a cast in una sottoclasse di IElement. |
anIShape.Diagram |
IDiagram che contiene la forma. |
anIShape.ParentShape |
Forma che contiene il tipo anIShape.Ad esempio, la forma di una porta è contenuta all'interno della forma di un componente. |
anIShape.ChildShapes |
Forme contenute all'interno di un tipo IShape o IDiagram. |
anIShape.GetChildShapes<IUseCase>() |
Forme contenute all'interno di un tipo IShape o IDiagram che rappresentano gli elementi del tipo specificato, ad esempio IUseCase. |
IShape iShape = ...; IShape<IClass> classShape = iShape.ToIShape<IClass>(); IClass aClass = classShape.Element; |
Esegue il cast di un tipo IShape generico a un tipo IShape<IElement> fortemente tipizzato. |
IShape<IClassifier> classifierShape; IShape<IUseCase> usecaseShape = classifierShape.ToIShape<IUseCase>(); |
Esegue il cast di una forma da un tipo di forma con parametri a un altro. |
Spostamento e ridimensionamento di forme
anIShape.Move(x, y, [width], [height]) |
Sposta o ridimensiona una forma. |
IDiagram.EnsureVisible( IEnumerable<IShape> shapes, bool zoomToFit = false) |
Attivare la finestra e scorrere il diagramma in modo che tutte le forme specificate siano visibili.Le forme devono essere tutte nel diagramma.Se zoomToFit è true, il diagramma verrà ridimensionato in modo che tutte le forme siano visibili. |
Per un esempio, vedere Definizione di un comando di allineamento.
Per rimuovere una forma da un diagramma
È possibile eliminare le forme di alcuni tipi di elemento senza eliminare l'elemento.
Elemento del modello |
Operazione da eseguire |
---|---|
Classificatore: classe, interfaccia, enumerazione, attore, caso di utilizzo o componente |
shape.Delete(); |
Comportamento: interazione o attività |
È possibile eliminare il diagramma dal progetto.Utilizzare IDiagram.FileName per ottenere il percorso. Non viene eliminato il comportamento dal modello. |
Qualsiasi altra forma |
Non è possibile eliminare in modo esplicito le altre forme da un diagramma.La forma scomparirà automaticamente se l'elemento viene eliminato dal modello o se la forma padre viene rimossa dal diagramma. |
Apertura e creazione di diagrammi
Per accedere al diagramma corrente dell'utente da un'estensione del comando o del movimento
Dichiarare questa proprietà importata nella classe:
[Import]
IDiagramContext Context { get; set; }
In un metodo accedere al diagramma:
IClassDiagram classDiagram =
Context.CurrentDiagram as IClassDiagram;
[!NOTA]
Un'istanza di IDiagram (e i relativi sottotipi come IClassDiagram) è valida solo all'interno del comando che viene elaborato.Non è consigliabile mantenere un oggetto IDiagram in una variabile persistente mentre il controllo viene restituito all'utente.
Per ulteriori informazioni, vedere Procedura: definire un comando di menu in un diagramma di modellazione.
Per ottenere un elenco di diagrammi aperti
Elenco dei diagrammi attualmente aperti nel progetto:
Context.CurrentDiagram.ModelStore.Diagrams()
Per accedere ai diagrammi in un progetto
È possibile utilizzare l'API di Visual Studio per aprire e creare progetti di modellazione e diagrammi.
Si noti il cast da EnvDTE.ProjectItem in 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)
{ ... } } }
Le istanze di IDiagram e i relativi sottotipi non sono validi dopo la restituzione del controllo a Visual Studio.
È inoltre possibile ottenere l'archivio modelli da un progetto Visual Studio:
Project project = ...;
IModelStore modelStore = (project as IModelingProject).Store;
Esempio: comando per allineare forme
Nel codice seguente viene implementato un comando di menu che consente di allineare accuratamente le forme.L'utente deve innanzitutto posizionare due o più forme con allineamento approssimativo, verticalmente od orizzontalmente.È quindi possibile utilizzare il comando di allineamento per allineare i centri.
Per rendere disponibile il comando, aggiungere il codice a un progetto di comando di menu, quindi distribuire agli utenti l'estensione risultante.Per ulteriori informazioni, vedere Procedura: definire un comando di menu in un diagramma di modellazione.
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;
}
}
}
Vedere anche
Concetti
Estensione di modelli e diagrammi UML
Procedura: esplorare il modello UML
Altre risorse
Esempio: comando di menu per allineare forme in un diagramma