Postupy: Definování obslužné rutiny gest v diagramu modelování
Ve Visual Studio Ultimate můžete definovat příkazy, které jsou provedeny, když uživatel poklepe na položky do diagramu UML nebo je přetáhne.Tato rozšíření můžete zabalit do rozšíření integrace Visual Studio (VSIX) a distribuovat ho dalším uživatelům aplikace Visual Studio Ultimate.
Pokud je již vestavěné chování pro typ diagramu a typ prvku, které chcete přetáhnout, možná nebudete moci přidat nebo přepsat toto chování.
Požadavky
Visual Studio SDK, kterou lze získat z Galerie sady Visual Studio.
Visual Studio Visualization and Modeling SDK, kterou lze získat z Galerie kódu Visual Studio Visualization and Modeling SDK.
Vytvoření obslužné rutiny gesta
Chcete-li definovat obslužnou rutinu gesta pro UML designer, musíte vytvořit třídu, která definuje chování obslužné rutiny gesta, a vložit tuto třídu do VSIX.VSIX funguje jako kontejner, který může obslužnou rutinu nainstalovat.Existují dva alternativní způsoby definování obslužné rutiny gesta:
Vytvořte obslužnou rutinu gesta ve vlastním souboru VSIX pomocí šablony projektu. Toto je rychlejší metoda.Pokud nechcete, aby vaši obslužnou rutinu kombinovat s jinými typy rozšíření například rozšířeními ověřování, vlastními položkami panelu nástrojů nebo příkazy nabídek, použijte ji.
Vytvořte obslužnou rutinu samostatného gesta a projekty VSIX. Tuto metodu použijte, pokud chcete sloučit několik typů rozšíření do stejného VSIX.Například pokud vaše obslužná rutina gesta očekává, že model bude dodržovat zvláštní omezení, můžete ji vložit do stejného VSIX jako metodu ověřování.
Vytvoření obslužné rutiny gesta ve vlastním souboru VSIX
V dialogovém okně Nový projekt, v části Modelování projektů vyberte Rozšíření gesta.
Otevřete soubor .cs v novém projektu a upravte třídu GestureExtension pro implementaci obslužné rutiny gesta.
Další informace viz Implementace obslužné rutiny gest.
Otestujte obslužnou rutinu gesta stisknutím klávesy F5.Další informace viz Provádění obslužné rutiny gest.
Nainstalujte obslužnou rutinu v jiném počítači zkopírováním souboru bin\*\*.vsix, který je sestaven projektem.Další informace viz Instalace obslužné rutiny gest.
Zde je alternativní postup:
Vytvoření samostatného projektu knihovny tříd (DLL) pro obslužnou rutinu gesta
Vytvořte projekt knihovny tříd v novém řešení Visual Studio nebo v existujícím řešení.
V nabídce Soubor zvolte položku Nový, Projekt.
V části Nainstalované šablony rozbalte položku Visual C# nebo Visual Basic, potom v prostředním sloupci zvolte možnost Knihovna tříd.
Do projektu přidejte následující odkazy.
Microsoft.VisualStudio.Modeling.Sdk.12.0
Microsoft.VisualStudio.Modeling.Sdk.Diagrams.12.0
Microsoft.VisualStudio.ArchitectureTools.Extensibility
Microsoft.VisualStudio.Uml.Interfaces
System.ComponentModel.Composition
System.Windows.Forms
Microsoft.VisualStudio.ArchitectureTools.Extensibility.Layer– Toto budete potřebovat pouze tehdy, pokud rozšiřujete diagramy vrstev.Další informace naleznete v tématu Rozšíření diagramů vrstev.
Přidejte soubor třídy do projektu a nastavte jeho obsah na následující kód.
[!POZNÁMKA]
Změňte oboru názvů a názvu třídy podle vašich potřeb.
using System.ComponentModel.Composition; using System.Linq; using System.Collections.Generic; using Microsoft.VisualStudio.Modeling.Diagrams; using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement; using Microsoft.VisualStudio.Modeling.ExtensionEnablement; using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml; using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation; using Microsoft.VisualStudio.Uml.AuxiliaryConstructs; using Microsoft.VisualStudio.Modeling; using Microsoft.VisualStudio.Uml.Classes; // ADD other UML namespaces if required namespace MyGestureHandler // CHANGE { // DELETE any of these attributes if the handler // should not work with some types of diagram. [ClassDesignerExtension] [ActivityDesignerExtension] [ComponentDesignerExtension] [SequenceDesignerExtension] [UseCaseDesignerExtension] // [LayerDesignerExtension] // Gesture handlers must export IGestureExtension: [Export(typeof(IGestureExtension))] // CHANGE class name public class MyGesture1 : IGestureExtension { [Import] public IDiagramContext DiagramContext { get; set; } /// <summary> /// Called when the user double-clicks on the diagram /// </summary> /// <param name="targetElement"></param> /// <param name="diagramPointEventArgs"></param> public void OnDoubleClick(ShapeElement targetElement, DiagramPointEventArgs diagramPointEventArgs) { // CHANGE THIS CODE FOR YOUR APPLICATION. // Get the target shape, if any. Null if the target is the diagram. IShape targetIShape = targetElement.CreateIShape(); // Do something... } /// <summary> /// Called repeatedly when the user drags from anywhere on the screen. /// Return value should indicate whether a drop here is allowed. /// </summary> /// <param name="targetMergeElement">References the element to be dropped on.</param> /// <param name="diagramDragEventArgs">References the element to be dropped.</param> /// <returns></returns> public bool CanDragDrop(ShapeElement targetMergeElement, DiagramDragEventArgs diagramDragEventArgs) { // CHANGE THIS CODE FOR YOUR APPLICATION. // Get the target element, if any. Null if the target is the diagram. IShape targetIShape = targetMergeElement.CreateIShape(); // This example allows drag of any UML elements. return GetModelElementsFromDragEvent(diagramDragEventArgs).Count() > 0; } /// <summary> /// Execute the action to be performed on the drop. /// </summary> /// <param name="targetDropElement"></param> /// <param name="diagramDragEventArgs"></param> public void OnDragDrop(ShapeElement targetDropElement, DiagramDragEventArgs diagramDragEventArgs) { // CHANGE THIS CODE FOR YOUR APPLICATION. } /// <summary> /// Retrieves UML IElements from drag arguments. /// Works for drags from UML diagrams. /// </summary> private IEnumerable<IElement> GetModelElementsFromDragEvent (DiagramDragEventArgs dragEvent) { //ElementGroupPrototype is the container for //dragged and copied elements and toolbox items. ElementGroupPrototype prototype = dragEvent.Data. GetData(typeof(ElementGroupPrototype)) as ElementGroupPrototype; // Locate the originals in the implementation store. IElementDirectory implementationDirectory = dragEvent.DiagramClientView.Diagram.Store.ElementDirectory; return prototype.ProtoElements.Select( prototypeElement => { ModelElement element = implementationDirectory .FindElement(prototypeElement.ElementId); ShapeElement shapeElement = element as ShapeElement; if (shapeElement != null) { // Dragged from a diagram. return shapeElement.ModelElement as IElement; } else { // Dragged from UML Model Explorer. return element as IElement; } }); } } }
Další informace o tom, co vložit do metod, viz Implementace obslužné rutiny gesta.
Příkaz nabídky je nutné přidat do projektu VSIX, který se chová jako kontejner pro instalaci příkazu.Pokud chcete, můžete zahrnout další součásti do stejného VSIX.
Přidání zvláštní obslužné rutiny gesta do projektu VSIX
Nepotřebujete tuto proceduru, pokud jste vytvořili obslužnou rutinu gesta s vlastním souborem VSIX.
Vytvořte projekt VSIX, pokud vaše řešení již existuje.
V Průzkumníku řešení v místní nabídce řešení zvolte Přidat, Nový projekt.
V části Nainstalované šablony rozbalte možnost Visual C# nebo Visual Basic a potom vyberte možnost Rozšiřitelnost.V prostředním sloupci zvolte Projekt VSIX.
Nastavte projekt VSIX jako projekt po spuštění pro řešení.
- V Průzkumníku řešení v místní nabídce projektu VSIX zvolte Nastavit jako projekt po spuštění.
V source.extension.vsixmanifest přidejte projekt knihovny tříd obslužné rutiny jako Komponentu MEF:
Na kartě MetaData nastavte název souboru VSIX.
Na kartě Cíle instalace nastavte sady Visual Studio Ultimate a Premium jako cíle.
Na kartě Aktiva vyberte možnost Nové a v dialogovém okně nastavte:
Typ = Komponenta MEF
Zdroj = Projekt v aktuálním řešení.
Projekt = Your class library project
Spuštění obslužné rutiny gesta
Pro účely testování spusťte obslužnou rutina gesta v režimu ladění.
Testování obslužné rutiny gesta
Stiskněte klávesu F5 nebo v nabídce Ladit klikněte na Začít ladění.
Spustí se experimentální instance aplikace Visual Studio.
Poradce při potížích: Pokud se nová aplikace Visual Studio nespustí:
Pokud máte více než jeden projekt, ujistěte se, že projekt VSIX je nastaven jako projekt při spuštění řešení.
V Průzkumníku řešení v místní nabídce startupu nebo projektu zvolte Vlastnosti.V editoru vlastností projektu zvolte kartu Ladění.Ujistěte se, že řetězec v poli Spustit externí program je úplný název cesty Visual Studio, obvykle:
C:\Program Files\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe
V experimentální instanci aplikace Visual Studio otevřete nebo vytvořte projekt modelování a otevřete nebo vytvořte diagram modelování.Použijte diagram, který patří k jednomu z typů uvedených v atributech vaší třídy obslužné rutiny gesta.
Poklepejte na libovolné místo v diagramu.Vaše obslužná rutina poklepání by měla být volána.
Přetáhněte element z průzkumníka UML do diagramu.Vaše obslužná rutina přetažení by měla být volána.
Poradce při potížích: Pokud obslužná rutina gesta nefunguje, ujistěte se, že:
Projekt obslužné rutiny gest je uveden jako komponenta MEF na kartě Aktiva v source.extensions.manifest v projektu VSIX.
Parametry všech vlastností Import a Export jsou platné.
Metoda CanDragDrop nevrací false.
Typ modelového diagramu, který používáte, (třída UML, sekvence a tak dále) je uveden jako jeden z atributů třídy obslužné rutiny gesta [ClassDesignerExtension], [SequenceDesignerExtension] a tak dále.
Neexistuje žádná vestavěná funkce již definovaná pro tento typ cíle a vynechaného prvku.
Implementace obslužné rutiny gesta
Metody obslužné rutiny gesta
Třída obslužné rutiny gesta implementuje a exportuje IGestureExtension.Metody, které je třeba definovat, jsou následující:
bool CanDragDrop (ShapeElement target, DiagramDragEventArgs dragEvent) |
Vraťte true, chcete-li povolit zavěšení zdrojového prvku odkazovaného v dragEvent na tento cíl. Tato metoda by neměla provést změny modelu.Musí pracovat rychle, protože se používá k určení stavu šipky, jak uživatel pohybuje ukazatelem myši. |
void OnDragDrop (ShapeElement target, DiagramDragEventArgs dragEvent) |
Aktualizujte model podle zdrojového objektu odkazovaného v dragEvent a cíli. Volána, když uživatel uvolní tlačítko myši po přetažení. |
void OnDoubleClick (ShapeElement target, DiagramPointEventArgs pointEvent) |
target je tvar, na který uživatel poklepal. |
Můžete napsat obslužné rutiny, které přijímají nejen UML, ale také celou řadu dalších položek, například soubory, uzly ve zobrazení třídy .NET, uzly v Průzkumníku architektury a tak dále.Uživatel můžete přetáhnout libovolnou z těchto položek do diagramu UML, pokud napíšete metodu OnDragDrop, která umí dekódovat serializovanou formu položek.Metody dekódování se liší podle různých položek.
Parametry těchto metod jsou:
ShapeElement target.Tvar nebo diagram, do kterého uživatel něco přetáhl.
ShapeElement je třída v implementaci, které je základem nástrojů modelování UML.Aby se snížilo riziko uvedení modelu a diagramů UML do nekonzistentního stavu, doporučujeme nepoužívat metody této třídy přímo.Místo toho zabalte prvek do IShapea pak použijte metody popsané v části Postupy: Zobrazení modelu v diagramech.
Získání IShape:
IShape targetIShape = target.CreateIShape(target);
Získání prvku modelu, který je cílen operací přetažení nebo poklepání:
IElement target = targetIShape.Element;
Můžete to přetypovat na konkrétnější typ prvku.
Získání úložiště modelu UML, které obsahuje model UML:
IModelStore modelStore = targetIShape.Element.GetModelStore();
Získání přístupu k hostiteli a poskytovateli služby:
target.Store.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE
DiagramDragEventArgs eventArgs.Tento parametr provede serializovanou formu zdrojového objektu operace přetažení:
System.Windows.Forms.IDataObject data = eventArgs.Data;
Prvky z mnoha různých druhů můžete přetáhnout do diagramu z různých částí aplikace Visual Studio nebo z plochy systému Windows.Různé typy prvků jsou kódovány různými způsoby v IDataObject.Chcete-li z něj extrahovat prvky, podívejte se do dokumentace pro příslušný typ objektu.
Pokud zdrojový objekt je prvek UML, který je přetažen z Průzkumníka modelů UML nebo jiný diagram UML, podívejte se n aPostupy: Získávání elementů modelu UML z objektu IDataObject.
Psaní kódu metod
Další informace o psaní kódu pro čtení a aktualizaci modelu naleznete v tématu Programování s rozhraním API UML.
Informace o přístupu k informacím modelu při operaci přetažení viz Postupy: Získávání elementů modelu UML z objektu IDataObject.
Pokud pracujete se sekvenčním diagramem, viz také Postupy: Úpravy sekvenčních diagramů pomocí rozhraní API UML.
Kromě parametrů metod můžete také deklarovat importovanou vlastnost ve vaší třídě, která poskytuje přístup k aktuálnímu diagramu a modelu.
[Import] public IDiagramContext DiagramContext { get; set; }
Deklarace IDiagramContext vám umožňuje napsat kód ve vašich metodách, který přistupuje k diagramu, aktuálnímu výběru a modelu:
IDiagram diagram = this.DiagramContext.CurrentDiagram;
foreach (IShape<IElement> shape in diagram.GetSelectedShapes<IElement>)
{ IElement element = shape.Element; ... }
IModelStore modelStore = diagram.ModelStore;
IModel model = modelStore.Root;
foreach (IDiagram diagram in modelStore.Diagrams) {...}
foreach (IElement element in modelStore.AllInstances<IUseCase>) {...}
Další informace naleznete v tématu Postupy: Procházení modelu UML.
Instalace a odinstalace rozšíření
Je možné nainstalovat rozšíření Visual Studio ve vašem počítači i v jiných počítačích.
Instalace rozšíření
V počítači vyhledejte soubor .vsix, který byl vytvořen vaším projektem VSIX.
V Průzkumníku řešení, v místní nabídce projektu VSIX, zvolte Otevřít složku v Průzkumníku Windows.
Vyhledejte soubor bin\*\YourProject.vsix
Zkopírujte soubor .vsix do cílového počítače, ve kterém chcete nainstalovat rozšíření.Může to být váš vlastní počítač nebo jiný.
Cílový počítač musí mít jednu z edic systému Visual Studio, kterou jste zadali v source.extension.vsixmanifest.
V cílovém počítači otevřete soubor .vsix.
Instalační služba rozšíření sady Visual Studio se otevře a nainstaluje rozšíření.
Spusťte nebo restartujte aplikaci Visual Studio.
Odinstalace rozšíření
V nabídce Nástroje zvolte tlačítko Správce rozšíření.
Rozbalte nainstalována rozšíření.
Vyberte rozšíření a poté vyberte možnost Odinstalovat.
Jen zřídka se chybné rozšíření nedokáže načíst a vytvoří sestavu v okně chyb, ale nezobrazí se ve Správci rozšíření.V takovém případě můžete odebrat rozšíření odstraněním souboru z:
%LocalAppData%\Local\Microsoft\VisualStudio\12.0\Extensions
Příklad
Následující příklad ukazuje, jak vytvořit životnosti v sekvenčním diagramu podle částí a portů komponentu přetažených z diagramu komponent.
Chcete-li ho otestovat, stiskněte klávesu F5.Otevře se experimentální instance aplikace Visual Studio.V tomto případě otevřete UML model a vytvořte komponentu v diagramu komponent.Přidejte tuto komponentu do některých rozhraní a částí vnitřních komponent.Vyberte rozhraní a části.Potom přetáhněte rozhraní a části do sekvenčního diagramu. (Táhněte od diagramu komponent až po kartu pro sekvenční diagram a potom dolů do sekvenčního diagramu.) Životnost se zobrazí u každého rozhraní a části.
Další informace o interakcích vazeb s diagramy sekvencí viz Postupy: Úpravy sekvenčních diagramů pomocí rozhraní API UML.
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;
using Microsoft.VisualStudio.Modeling.ExtensionEnablement;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Presentation;
using Microsoft.VisualStudio.Uml.AuxiliaryConstructs;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.Uml.Interactions;
using Microsoft.VisualStudio.Uml.CompositeStructures;
using Microsoft.VisualStudio.Uml.Components;
/// <summary>
/// Creates lifelines from component ports and parts.
/// </summary>
[Export(typeof(IGestureExtension))]
[SequenceDesignerExtension]
public class CreateLifelinesFromComponentParts : IGestureExtension
{
[Import]
public IDiagramContext Context { get; set; }
/// <summary>
/// Called by the modeling framework when
/// the user drops something on a target.
/// </summary>
/// <param name="target">The target shape or diagram </param>
/// <param name="dragEvent">The item being dragged</param>
public void OnDragDrop(ShapeElement target,
DiagramDragEventArgs dragEvent)
{
ISequenceDiagram diagram = Context.CurrentDiagram
as ISequenceDiagram;
IInteraction interaction = diagram.Interaction;
if (interaction == null)
{
// Sequence diagram is empty: create an interaction.
interaction = diagram.ModelStore.Root.CreateInteraction();
interaction.Name = Context.CurrentDiagram.Name;
diagram.Bind(interaction);
}
foreach (IConnectableElement connectable in
GetConnectablesFromDrag(dragEvent))
{
ILifeline lifeline = interaction.CreateLifeline();
lifeline.Represents = connectable;
lifeline.Name = connectable.Name;
}
}
/// <summary>
/// Called by the modeling framework to determine whether
/// the user can drop something on a target.
/// Must not change anything.
/// </summary>
/// <param name="target">The target shape or diagram</param>
/// <param name="dragEvent">The item being dragged</param>
/// <returns>true if this item can be dropped on this target</returns>
public bool CanDragDrop(ShapeElement target,
DiagramDragEventArgs dragEvent)
{
IEnumerable<IConnectableElement> connectables = GetConnectablesFromDrag(dragEvent);
return connectables.Count() > 0;
}
///<summary>
/// Get dragged parts and ports of an IComponent.
///</summary>
private IEnumerable<IConnectableElement>
GetConnectablesFromDrag(DiagramDragEventArgs dragEvent)
{
foreach (IElement element in
GetModelElementsFromDragEvent(dragEvent))
{
IConnectableElement part = element as IConnectableElement;
if (part != null)
{
yield return part;
}
}
}
/// <summary>
/// Retrieves UML IElements from drag arguments.
/// Works for drags from UML diagrams.
/// </summary>
private IEnumerable<IElement> GetModelElementsFromDragEvent
(DiagramDragEventArgs dragEvent)
{
//ElementGroupPrototype is the container for
//dragged and copied elements and toolbox items.
ElementGroupPrototype prototype =
dragEvent.Data.
GetData(typeof(ElementGroupPrototype))
as ElementGroupPrototype;
// Locate the originals in the implementation store.
IElementDirectory implementationDirectory =
dragEvent.DiagramClientView.Diagram.Store.ElementDirectory;
return prototype.ProtoElements.Select(
prototypeElement =>
{
ModelElement element = implementationDirectory
.FindElement(prototypeElement.ElementId);
ShapeElement shapeElement = element as ShapeElement;
if (shapeElement != null)
{
// Dragged from a diagram.
return shapeElement.ModelElement as IElement;
}
else
{
// Dragged from UML Model Explorer.
return element as IElement;
}
});
}
public void OnDoubleClick(ShapeElement targetElement, DiagramPointEventArgs diagramPointEventArgs)
{
}
}
Kód GetModelElementsFromDragEvent() je popsán v části Postupy: Získávání elementů modelu UML z objektu IDataObject.
Viz také
Koncepty
Postupy: Definování a instalace rozšíření modelování
Rozšiřování modelů a diagramů UML
Postupy: Definování příkazu nabídky v diagramu modelování