Comment : afficher un modèle sur des diagrammes
Dans le code de programme d'une extension de Visual Studio Ultimate, vous pouvez contrôler l'affichage des éléments de modèles dans les diagrammes.
Dans cette rubrique :
Pour afficher un élément dans un diagramme
Accès aux formes qui représentent un élément
Déplacement et redimensionnement de formes
Pour supprimer une forme d'un diagramme
Ouverture et création de diagrammes
Exemple : commande pour l'alignement de formes
Pour afficher un élément dans un diagramme
Lorsque vous créez un élément tel qu'un cas d'usage ou une action, l'utilisateur peut le visualiser dans l'Explorateur de modèles UML. Cependant, l'élément concerné ne s'affiche pas toujours automatiquement dans un diagramme.Dans certains cas, vous devez écrire le code pour l'afficher.Le tableau suivant récapitule les possibilités.
Type d'élément |
Exemple : |
Pour l'afficher, votre code doit |
---|---|---|
Classifieur |
Class Component Actor Use Case |
Créez des formes associées dans les diagrammes spécifiés.Vous pouvez créer n'importe quel nombre de formes pour chaque classifieur. diagram.Display<modelElementType> (modelElement, parentShape, xPosition , yPosition); Affectez à parentShape la valeur null pour une forme au niveau supérieur du diagramme. Pour afficher une forme dans une autre : IShape<IUseCase> usecaseShape = useCaseDiagram.Display (useCase, subsystemShape, subsystemShape.XPosition + 5, subsystemShape.YPosition + 5);
Remarque
Si vous exécutez l'Affichage dans une transaction ILinkedUndo, la méthode ne retourne parfois aucun IShape.Cependant, la forme est correctement créée et demeure accessible à l'aide d'IElement.Shapes().
|
Enfant de classifieur |
Attribut, opération, Élément, port |
Automatique - aucun code requis. S'affiche en tant que partie du parent. |
Comportement |
Interaction (séquence), Activité |
Liez le comportement à un diagramme approprié. Chaque comportement peut être lié à plusieurs diagrammes simultanément. Par exemple : sequenceDiagram.Bind(interaction); activityDiagram.Bind(activity); |
Enfant de comportement |
Lignes de vie, messages, actions, nœuds d'objets |
Automatique - aucun code requis. S'affiche si le parent est lié à un diagramme. |
Relation |
Association, généralisation, flux, dépendance |
Automatique - aucun code requis. S'affiche dans chaque diagramme dans lequel les deux extrémités sont présentes. |
Accès aux formes qui représentent un élément
La forme qui représente un élément appartient aux types suivants :
IShape
IShape<TypeÉlément>
où TypeÉlément correspond à un type de l'élément de modèle comme IClass ou IUseCase.
anElement.Shapes () |
Tous les IShapes qui représentent cet élément dans les diagrammes ouverts. |
anElement.Shapes(aDiagram) |
Tous les IShapes qui représentent cet élément dans un diagramme particulier. |
anIShape.GetElement() |
IElement que la forme représente.Vous le casteriez normalement en une sous-classe d'IElement. |
anIShape.Diagram |
IDiagram qui contient la forme. |
anIShape.ParentShape |
Forme qui contient anIShape.Par exemple, une forme de port est contenue dans une forme de composant. |
anIShape.ChildShapes |
Formes contenues dans un IShape ou un IDiagram. |
anIShape.GetChildShapes<IUseCase>() |
Formes contenues dans un IShape ou un IDiagram qui représentent des éléments du type spécifié, comme IUseCase. |
IShape iShape = ...; IShape<IClass> classShape = iShape.ToIShape<IClass>(); IClass aClass = classShape.Element; |
Castez un IShape générique en IShape<IElement> fortement typé. |
IShape<IClassifier> classifierShape; IShape<IUseCase> usecaseShape = classifierShape.ToIShape<IUseCase>(); |
Castez une forme d'un type de forme paramétrable à un autre. |
Déplacement et redimensionnement de formes
anIShape.Move(x, y, [width], [height]) |
Déplacez ou redimensionnez une forme. |
IDiagram.EnsureVisible( IEnumerable<IShape> shapes, bool zoomToFit = false) |
Activez la fenêtre et faites défiler le diagramme afin que toutes les formes données soient visibles.Les formes doivent toutes être dans le diagramme.Si zoomToFit a la valeur True, le diagramme sera mis à l'échelle si cela est requis pour que toutes les formes soient visibles. |
Pour obtenir un exemple, consultez Définition d'une commande d'alignement.
Pour supprimer une forme d'un diagramme
Vous pouvez supprimer des formes de certains types d'éléments sans devoir supprimer l'élément lui-même.
Élément de modèle |
Pour supprimer la forme |
---|---|
Classifieur : classe, interface, énumération, acteur, cas d'usage ou composant |
shape.Delete(); |
Comportement : interaction ou activité |
Vous pouvez supprimer le diagramme du projet.Utilisez IDiagram.FileName pour obtenir le chemin d'accès. Cette action n'entraîne pas la suppression du comportement du modèle. |
N'importe quelle autre forme |
Vous ne pouvez pas supprimer explicitement d'autres formes d'un diagramme.La forme disparaîtra automatiquement si l'élément est supprimé du modèle ou si la forme parent l'est du diagramme. |
Ouverture et création de diagrammes
Pour accéder au diagramme actuel de l'utilisateur à partir d'une extension de commande ou de mouvement
Déclarez cette propriété importée dans votre classe :
[Import]
IDiagramContext Context { get; set; }
Dans une méthode, accédez au diagramme :
IClassDiagram classDiagram =
Context.CurrentDiagram as IClassDiagram;
[!REMARQUE]
Une instance d'IDiagram (et ses sous-types tels qu'IClassDiagram) est valide uniquement dans la commande que vous traitez.Il n'est pas recommandé de conserver un objet IDiagram dans une variable qui est persistante alors que le contrôle est retourné à l'utilisateur.
Pour plus d'informations, consultez Comment : définir une commande de menu sur un diagramme de modélisation.
Pour obtenir la liste des diagrammes ouverts
Liste des diagrammes actuellement ouverts dans le projet :
Context.CurrentDiagram.ModelStore.Diagrams()
Pour accéder aux diagrammes dans un projet
L'API Visual Studio peut être utilisée pour ouvrir et créer des projets de modélisation et des diagrammes.
Remarquez le cast d'EnvDTE.ProjectItem vers 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)
{ ... } } }
Les instances d'IDiagram et ses sous-types ne sont pas valides une fois le contrôle retourné à Visual Studio.
Vous pouvez également obtenir le magasin de modèles à partir d'un projet Visual Studio :
Project project = ...;
IModelStore modelStore = (project as IModelingProject).Store;
Exemple : commande pour l'alignement de formes
Le code suivant implémente une commande de menu qui aligne correctement les formes.L'utilisateur doit d'abord placer deux formes ou plus dans un alignement approximatif, verticalement ou horizontalement.Ensuite, la commande peut être utilisée pour aligner leur centre.
Pour rendre la commande disponible, ajoutez ce code à un projet de commande de menu, puis déployez l'extension résultante pour vos utilisateurs.Pour plus d'informations, consultez Comment : définir une commande de menu sur un diagramme de modélisation.
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;
}
}
}
Voir aussi
Concepts
Extension de modèles et de diagrammes UML
Comment : naviguer dans le modèle UML
Autres ressources
Exemple : Commande pour aligner des formes sur un diagramme (page éventuellement en anglais)
Exemple : création d'éléments, de formes et de stéréotypes (page éventuellement en anglais)