Share via


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);

NotaNota
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

Ee330928.collapse_all(it-it,VS.110).gifPer 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.

Ee330928.collapse_all(it-it,VS.110).gifPer 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

Esempio: creazione di elementi, forme e stereotipi