如何:在圖表上顯示模型

在 Visual Studio Ultimate 擴充功能的程式碼中,您可以控制模型項目在圖表上顯示的方式。

  • 本主題內容:

    • 若要在圖表上顯示項目

    • 存取代表項目的圖案

    • 移動圖案及調整圖案大小

    • 若要從圖表移除圖案

    • 開啟及建立圖表

    • 範例:對齊圖案的命令

若要在圖表上顯示項目

當您建立項目 (例如,使用案例或動作) 時,使用者可以在 [UML 模型總管] 中看見該項目,但是該項目不一定會自動出現在圖表中。 在某些情況下,您必須撰寫程式碼來顯示它。 下表摘要說明一些替代方法。

 

項目的類型

例如

若要顯示此內容,您的程式碼必須

Classifier

Class

Component

Actor

Use Case

在指定的圖表上建立相關聯的圖案。 您可以為每一個 Classifier 建立任意數目的圖案。

diagram.Display<modelElementType>

(modelElement, parentShape,

xPosition , yPosition);

針對圖表頂端的圖案,將 parentShape 設為 null。

在某一個圖案內顯示另一個圖案。

IShape<IUseCase> usecaseShape =

useCaseDiagram.Display

(useCase,

subsystemShape,

subsystemShape.XPosition + 5,

subsystemShape.YPosition + 5);

注意事項注意事項

如果您在 ILinkedUndo 交易內執行 Display,這個方法有時候不會傳回 IShape,但是圖案會正確建立,並且可以使用 IElement.Shapes(). 存取。

Classifier 的子系

屬性、作業、

組件、通訊埠

自動:不需要程式碼。

它會做為父系的一部分顯示。

行為

互動 (序列),

活動

將行為繫結至適當的圖表。

每一個行為每次最多可以繫結至一個圖表。

例如:

sequenceDiagram.Bind(interaction);

activityDiagram.Bind(activity);

行為的子系

生命線、訊息、動作、物件節點

自動:不需要程式碼。

它會在父系繫結至圖表時顯示。

關聯性

關聯、一般化、流程、相依性

自動:不需要程式碼。

它會在兩端都顯示的每一個圖表上顯示。

 

存取代表項目的圖案

代表項目的圖案屬於下列型別:

IShape

IShape<ElementType>

其中 ElementType 是模型項目的型別,例如 IClass 或 IUseCase。

anElement.Shapes ()

開啟的圖表中所有表示此項目的 IShapes。

anElement.Shapes(aDiagram)

在特殊圖表上表示此項目的所有 IShapes。

anIShape.GetElement()

圖案所表示的 IElement。 您通常會將其轉換成 IElement 的子類別。

anIShape.Diagram

包含圖案的 IDiagram。

anIShape.ParentShape

包含 anIShape 的圖案。 例如,通訊埠圖案包含在元件圖案內。

anIShape.ChildShapes

IShape 或 IDiagram 內含的圖案。

anIShape.GetChildShapes<IUseCase>()

IShape 或 IDiagram 內含的圖案,代表指定型別的項目,例如 IUseCase。

IShape iShape = ...;

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

IClass aClass = classShape.Element;

將泛型 IShape 轉換成強型別 IShape<IElement>。

IShape<IClassifier> classifierShape;

IShape<IUseCase> usecaseShape =

classifierShape.ToIShape<IUseCase>();

在參數化圖案型別之間轉換圖案。

移動圖案及調整圖案大小

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

移動圖案或調整圖案大小。

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

啟動視窗並捲動圖表,使所有指定的圖案都能呈現。 這些圖案全都必須在圖表上。 如果 zoomToFit 為 true,圖表即會視需要進行縮放,使所有圖案都能呈現。

如需範例,請參閱定義對齊命令。

若要從圖表移除圖案

您可以刪除一些項目類型的圖案,而不刪除該項目。

模型項目

若要移除圖案

Classifier:類別、介面、列舉、行動、使用案例或元件

shape.Delete();

行為:互動或活動

您可以從專案中刪除圖表。 請使用 IDiagram.FileName 取得路徑。

這樣做不會刪除模型的行為。

任何其他圖案

您無法明確刪除圖表中的其他圖案。 如果從模型中刪除項目,或是從圖表中移除父圖案,則圖案將自動消失。

開啟及建立圖表

若要從命令或軌跡擴充功能存取使用者目前的圖表

在類別中宣告此匯入的屬性:

[Import]

IDiagramContext Context { get; set; }

 

在方法中存取圖表:

IClassDiagram classDiagram =

Context.CurrentDiagram as IClassDiagram;

注意事項注意事項

只有在您所處理的命令中,IDiagram 的執行個體 (及其子類型,如 IClassDiagram) 才有效。建議您不要將 IDiagram 物件保存在使用者重新取得控制權後仍會保留的變數中。

如需詳細資訊,請參閱如何:在模型圖表上定義功能表命令

若要取得開啟圖表的清單

專案中目前開啟之圖表的清單:

Context.CurrentDiagram.ModelStore.Diagrams()

若要存取專案中的圖表

Visual Studio API 可用以開啟及建立模型專案和圖表。

請留意從 EnvDTE.ProjectItem 到 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)
  { ... } } }

在您將控制權傳回給 Visual Studio 後,IDiagram 的執行個體及其子類型即無效。

您也可以從 Visual Studio 專案取得模型存放區:

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

範例:對齊圖案的命令

下列程式碼實作工整對齊圖案的功能表命令。 使用者必須先以接近垂直或水平對齊的方式放置兩個以上的圖案。 接著對齊命令可用來將圖案置中對齊。

若要讓使用者使用此命令,請將此程式碼加入至功能表命令專案,然後部署產生的擴充功能。 如需詳細資訊,請參閱如何:在模型圖表上定義功能表命令

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

請參閱

概念

擴充 UML 模型與圖表

如何:巡覽 UML 模型

其他資源

範例:在圖表上工整對齊形狀功能表命令

範例:建立項目、形狀和造型