Sdílet prostřednictvím


Přizpůsobení chování kopie

V jazyce specifické pro doménu (DSL), vytvořené pomocí Visual Studio vizualizaci a modelování SDK můžete změnit, co se stane, pokud uživatel zkopíruje vloží prvky.

Standardní kopírovat a vložit chování

Chcete-li povolit kopírování, nastavte Povolit kopírování, vkládání vlastnost Editor uzel v aplikaci Explorer DSL.

Ve výchozím nastavení Pokud uživatel zkopíruje prvky do schránky následující prvky zkopírují také:

  • Vložený následovníci vybrané prvky.(Prvky, které jsou cíle vložení vztahů, které jsou na získání, zkopíruje prvky.)

  • Vztah vazby mezi kopírované prvky.

Toto pravidlo platí rekurzivně kopírované prvky a odkazy.

Zkopírované a vložené prvky

Serializované a uloženy v kopírované prvky a odkazy ElementGroupPrototype (EGP), která je umístěna do schránky.

Obrázek zkopírovaný prvků je také umístěn do schránky.To umožňuje uživateli vložit do jiné aplikace, jako je například aplikace Word.

Uživatele můžete vložit zkopírovaný prvků na cíl, který může přijmout elementy podle definice DSL.V DSL, generovaných z šablony součástí řešení, například uživatel můžete vložit porty na součásti, ale není do diagramu; a můžete vložit součásti do diagramu, ale není na ostatní součásti.

Úpravy, kopírovat a vložit chování

Další informace o přizpůsobení modelu pomocí kódu programu viz Navigace a aktualizace modelu v kódu programu.

  • Povolit nebo zakázat kopírovat, vyjmout a vložit.
    V aplikaci Explorer DSL, nastavte Povolit kopírování, vkládání vlastnost Editor uzel.

  • Kopírování propojení na stejný cíl. Například mít pole zkopírované komentáře spojené s předmětem téhož prvku.
    Nastavit Šíří kopie vlastnost role kopie Propagate propojit pouze.Další informace naleznete v tématu Přizpůsobení chování Kopírovat odkaz.

  • Kopírovat propojené prvky. Například při kopírování nového prvku kopie všech propojených políčka jsou také provedeno.
    Nastavit Šíří kopie vlastnost role kopie Propagate propojit a opačné aktéra role.Další informace naleznete v tématu Přizpůsobení chování Kopírovat odkaz.

  • Zkopírováním a vložením rychle duplicitní prvky. Obvykle je stále vybrán položku, kterou jste právě zkopírovali a stejného typu prvku na něj nelze vložit.
    Direktivu sloučit prvek přidat do domény třídy a nastavte ji na sloučení vpřed k nadřazené třídy.To bude mít stejný účinek na operace přetažení.Další informace naleznete v tématu Přizpůsobení vytvoření prvku a pohyb.

    -nebo-

    Před přepsáním vkládání prvků, vyberte diagram ClipboardCommandSet.ProcessOnPasteCommand().Přidáte vlastní soubor projektu DslPackage tento kód:

    namespace Company.MyDsl {
    using System.Linq;
    using Microsoft.VisualStudio.Modeling.Diagrams; 
    using Microsoft.VisualStudio.Modeling.Shell;
    partial class MyDslClipboardCommandSet
    {
      protected override void ProcessOnMenuPasteCommand()
      {
     // Deselect the current selection after copying:
     Diagram diagram = (this.CurrentModelingDocView as SingleDiagramDocView).Diagram;
        this.CurrentModelingDocView
         .SelectObjects(1, new object[] { diagram }, 0);
      }
    } }
    
  • Vytvořte další odkazy, pokud uživatel vloží do vybraného cíle. Například pokud je pole pro komentář vložen element, odkaz provedené mezi nimi.
    Direktivu korespondence prvek přidat do cílové domény třídy a nastavte ji na zpracování hromadné korespondence přidáním odkazů.To bude mít stejný účinek na operace přetažení.Další informace naleznete v tématu Přizpůsobení vytvoření prvku a pohyb.

    -nebo-

    Přepsat ClipboardCommandSet.ProcessOnPasteCommand() po volání metody základní vytvořit další odkazy.

  • Vlastní formáty, ve kterých lze kopírovat prvky na externí aplikace – například rastrový obrázek formuláře přidat ohraničení.
    Přepsat MyDslClipboardCommandSet.ProcessOnMenuCopyCommand() DslPackage projektu.

  • Upravte, jak jsou prvky zkopírován do schránky pomocí příkazu Kopírovat, ale ne v operaci přetažení.
    Přepsat MyDslClipboardCommandSet.CopyModelElementsIntoElementGroupPrototype() DslPackage projektu.

  • Zachovat rozložení obrazců pomocí Kopírovat a vložit.
    Pokud uživatel zkopíruje více obrazců, můžete zachovat jejich relativní polohy při jejich vložení.Tento postup je znázorněn v příkladu v VMSDK: ukázkové diagramy obvodu.

    Chcete-li dosáhnout tohoto efektu, přidejte do zkopírovaných ElementGroupPrototype tvarů a spojovacích čar.ElementOperations.CreateElementGroupPrototype() je nejvhodnější metoda potlačit.Chcete-li to provést, přidejte následující kód Dsl projektu:

    public class MyElementOperations : DesignSurfaceElementOperations
    {
      // Create an EGP to add to the clipboard.
      // Called when the elements to be copied have been
      // collected into an ElementGroup.
     protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup, ICollection<ModelElement> elements, ClosureType closureType)
      {
     // Add the shapes and connectors:
     // Get the elements already in the group:
        ModelElement[] mels = elementGroup.ModelElements
            .Concat(elementGroup.ElementLinks) // Omit if the paste target is not the diagram.
            .ToArray();
     // Get their shapes:
        IEnumerable<PresentationElement> shapes = 
           mels.SelectMany(mel => 
                PresentationViewsSubject.GetPresentation(mel));
        elementGroup.AddRange(shapes);
    
     return base.CreateElementGroupPrototype
               (elementGroup, elements, closureType);
      }
    
     public MyElementOperations(IServiceProvider serviceProvider, ElementOps1Diagram diagram)
          : base(serviceProvider, diagram)
      { }
    }
    
    // Replace the standard ElementOperations
    // singleton with your own:
    partial class MyDslDiagram // EDIT NAME
    {
     /// <summary>
     /// Singleton ElementOperations attached to this diagram.
     /// </summary>
     public override DesignSurfaceElementOperations ElementOperations
      {
     get
        {
     if (singleton == null)
          {
            singleton = new MyElementOperations(this.Store as IServiceProvider, this);
          }
     return singleton;
        }
      }
     private MyElementOperations singleton = null;
    }
    
  • Vložení obrazců do zvoleného umístění, jako je například aktuální pozice kurzoru.
    Pokud uživatel zkopíruje více obrazců, můžete zachovat jejich relativní polohy při jejich vložení.Tento postup je znázorněn v příkladu v VMSDK: ukázkové diagramy obvodu.

    Chcete-li dosáhnout tohoto efektu přepsat ClipboardCommandSet.ProcessOnMenuPasteCommand() používat specifické umístění verzi ElementOperations.Merge().Chcete-li to provést, přidejte následující kód v DslPackage projektu:

    
    partial class MyDslClipboardCommandSet // EDIT NAME
    {
       /// <summary>
        /// This method assumes we only want to paste things onto the diagram
        /// - not onto anything contained in the diagram.
        /// The base method pastes in a free space on the diagram.
        /// But if the menu was used to invoke paste, we want to paste in the cursor position.
        /// </summary>
        protected override void ProcessOnMenuPasteCommand()
        {
    
      NestedShapesSampleDocView docView = this.CurrentModelingDocView as NestedShapesSampleDocView;
    
          // Retrieve data from clipboard:
          System.Windows.Forms.IDataObject data = System.Windows.Forms.Clipboard.GetDataObject();
    
          Diagram diagram = docView.CurrentDiagram;
          if (diagram == null) return;
    
          if (!docView.IsContextMenuShowing)
          {
            // User hit CTRL+V - just use base method.
    
            // Deselect anything that's selected, otherwise
            // pasted item will be incompatible:
            if (!this.IsDiagramSelected())
            {
              docView.SelectObjects(1, new object[] { diagram }, 0);
            }
    
            // Paste into a convenient spare space on diagram:
        base.ProcessOnMenuPasteCommand();
          }
          else
          {
            // User right-clicked - paste at mouse position.
    
            // Utility class:
            DesignSurfaceElementOperations op = diagram.ElementOperations;
    
            ShapeElement pasteTarget = diagram;
    
            // Check whether what's in the paste buffer is acceptable on the target.
            if (pasteTarget != null && op.CanMerge(pasteTarget, data))
            {
    
            // Although op.Merge would be a no-op if CanMerge failed, we check CanMerge first
              // so that we don't create an empty transaction (after which Undo would be no-op).
              using (Transaction t = diagram.Store.TransactionManager.BeginTransaction("paste"))
              {
                PointD place = docView.ContextMenuMousePosition;
                op.Merge(pasteTarget, data, PointD.ToPointF(place));
                t.Commit();
              }
            }
          }
        }
      }
    
  • Umožní uživateli přetáhnout prvky.
    Viz téma Jak: Přidat ukazatel a přetažení.

Přizpůsobení chování Kopírovat odkaz

Pokud uživatel zkopíruje prvek, je standardní chování také zkopírovány všechny vložené prvky.Můžete upravit standardní chování pro kopírování.V definici DSL vyberte roli na straně 1 relace a nastavit vlastnosti okna Šíří kopie hodnotu.

Propaguje vlastnost Kopírovat roli domény

Existují tři hodnoty:

  • Kopie nejsou rozšířena

  • Šířit kopie pouze - propojení po vložení skupiny, novou kopii tohoto spojení bude odkazovat na existující prvek na konci propojení.

  • Šířit kopie propojení a opačné role přehrávače - zkopírované skupina obsahuje kopii prvku na konci propojení.

Vliv kopírování s PropagateCopyToLinkOnly

Změny, které ovlivní prvky a obraz, který je zkopírován.

Programování kopírovat a vložit chování

Mnohé aspekty chování linku DSL ke kopírování, vložení, vytvoření a odstranění objektů se řídí instanci ElementOperations s do diagramu.Můžete změnit chování vašeho DSL vyplývající vlastní třídy z ElementOperations a přepsání ElementOperations vlastnost třídy v diagramu.

Tip

Další informace o přizpůsobení modelu pomocí kódu programu viz Navigace a aktualizace modelu v kódu programu.

Sekvenční diagram pro kopírováníSekvenční diagram vložit operace

Definovat vlastní ElementOperations

  1. V novém souboru projektu DSL vytvořit třídu, která je odvozena od DesignSurfaceElementOperations.

  2. Přidáte definici třídy částečné třídy v diagramu.Název třídy lze nalézt v Dsl\GeneratedCode\Diagrams.cs.

    V diagramu třídy přepsat ElementOperations vrátit instance vaše podtřída ElementOperations.Zpět stejné instance v každém volání.

Přidáte tento kód do souboru vlastní kód v DslPackage projektu:

using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.ExtensionEnablement;

  public partial class MyDslDiagram
  {
    public override DesignSurfaceElementOperations ElementOperations
    {
      get
      {
        if (this.elementOperations == null)
        {
          this.elementOperations = new MyElementOperations(this.Store as IServiceProvider, this);
        }
        return this.elementOperations;
      }
    }
    private MyElementOperations elementOperations = null;
  }

  public class MyElementOperations : DesignSurfaceElementOperations
  {
    public MyElementOperations(IServiceProvider serviceProvider, MyDslDiagram diagram)
      : base(serviceProvider, diagram)
    { }
    // Overridden methods follow
  }

Příjem zboží přetaženým z jiných modelů

ElementOperations lze také definovat chování kopírování, přesun, odstranění a a přetažení.Jako ukázku použití ElementOperations například zadána zde definuje vlastní chování a přetažení.Však pro tento účel můžete zvážit alternativní metoda popsaná v Jak: Přidat ukazatel a přetažení, který je více rozšiřitelný.

Ve své třídě ElementOperations definujte dvěma způsoby:

  • CanMerge(ModelElement targetElement, System.Windows.Forms.IDataObject data)které určuje, zda zdrojový prvek může být přetažen cílového obrazce, spojnice nebo diagramu.

  • MergeElementGroupPrototype(ModelElement targetElement, ElementGroupPrototype sourcePrototype)který spojuje zdrojový prvek do cíle.

Ff521398.collapse_all(cs-cz,VS.110).gifCanMerge()

[CanMerge()]se nazývá zjistit názor, že by měla být věnována uživatele při pohybu myší přes diagramu.Parametry metody jsou prvek, jehož prostřednictvím je výběru ukázáním myši a údaje o zdroji, ze kterého byla provedena operace přetažení.Uživatel z můžete přetáhnout kamkoli na obrazovce.Zdrojový objekt proto může být mnoho různých typů a může být serializován v různých formátech.Pokud je zdrojem DSL nebo UML model, je parametr data serializace ElementGroupPrototype.Operace přetahování, kopírování a nástrojů slouží ke znázornění fragmenty modely ElementGroupPrototypes.

Prototyp skupiny prvku může obsahovat libovolný počet prvků a odkazy.Typy prvků lze identifikovat podle identifikátorů GUID.Identifikátor GUID je tvar, který byl přetažen není základní prvek modelu.V následujícím příkladu CanMerge() vrátí hodnotu true, když přetáhnete obrazec Třída z diagramu UML do tohoto diagramu.

public override bool CanMerge(ModelElement targetShape, System.Windows.Forms.IDataObject data)
 {
  // Extract the element prototype from the data.
  ElementGroupPrototype prototype = ElementOperations.GetElementGroupPrototype(this.ServiceProvider, data);
  if (targetShape is MyTargetShape && prototype != null &&
        prototype.RootProtoElements.Any(rootElement => 
          rootElement.DomainClassId.ToString() 
          ==  "3866d10c-cc4e-438b-b46f-bb24380e1678")) // Guid of UML Class shapes
          // or SourceClass.DomainClassId
        return true;
   return base.CanMerge(targetShape, data);
 }

MergeElementGroupPrototype()

Tato metoda je volána, když uživatel umístí přetahovaný prvku do diagramu, tvaru nebo konektoru.Cílový prvek jej by sloučit přetažené obsahu.V tomto příkladu kódu určuje, zda rozpoznává kombinaci typů cíl a prototyp; Pokud ano, metoda převede přetažených prvků na prototypu prvků, které by měly být přidány do modelu.Základní metoda se nazývá provést sloučení, buď převedené nebo nepřevedené prvků.

    public override void MergeElementGroupPrototype(ModelElement targetShape, ElementGroupPrototype sourcePrototype)
    {
      ElementGroupPrototype prototypeToMerge = sourcePrototype;
      MyTargetShape pel = targetShape as MyTargetShape;
      if (pel != null)
      {
        prototypeToMerge = ConvertDraggedTypeToLocal(pel, sourcePrototype);
      }
      if (prototypeToMerge != null)
        base.MergeElementGroupPrototype(targetShape, prototypeToMerge);
    }

V tomto příkladu se zabývá prvky třídy UML přetaženým z diagramu UML třídy.Modem DSL není určen k ukládání třídy UML přímo, ale místo toho jsme vytvoření prvku DSL pro každou třídu přetažené UML.To by užitečné, například pokud je modem DSL diagramu instance.Uživatele nelze přetáhnout tříd diagram vytvoření instance třídy.

    private ElementGroupPrototype ConvertDraggedTypeToLocal (MyTargetShape snapshot, ElementGroupPrototype prototype)
    {
      // Find the UML project:
      EnvDTE.DTE dte = snapshot.Store.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
      foreach (EnvDTE.Project project in dte.Solution.Projects)
      {
        IModelingProject modelingProject = project as IModelingProject;
        if (modelingProject == null) continue; // not a modeling project
        IModelStore store = modelingProject.Store;
        if (store == null) continue;
        // Look for the shape that was dragged:
        foreach (IDiagram umlDiagram in store.Diagrams())
        {
          // Get modeling diagram that implements UML diagram:
          Diagram diagram = umlDiagram.GetObject<Diagram>();
          Guid elementId = prototype.SourceRootElementIds.FirstOrDefault();
          ShapeElement shape = diagram.Partition.ElementDirectory.FindElement(elementId) as ShapeElement;
          if (shape == null) continue;
          IClass classElement = shape.ModelElement as IClass;
          if (classElement == null) continue;
          
          // Create a prototype of elements in my DSL, based on the UML element:
          Instance instance = new Instance(snapshot.Store);
          instance.Type = classElement.Name;
          // Pack them into a prototype:
          ElementGroup group = new ElementGroup(instance);
          return group.CreatePrototype();
        }
      }
      return null;
    }

Standardní chování kopie

Přepsat metody, které můžete změnit chování kopírování zobrazí kód v této části.Chcete-li vidět jak dosáhnout vlastní úpravy, tato část zobrazuje kód, který přepíše účastní kopírování metody, ale nezmění standardní chování.

Když uživatel stiskne kombinaci kláves CTRL + C nebo používá příkaz Kopírovat, metoda ProcessOnMenuCopyCommand se nazývá.Uvidíte, jak toto nastavení DslPackage\Generated Code\CommandSet.cs.Další informace o nastavení jak jsou příkazy, viz Jak: přidat příkaz místní nabídky.

Můžete potlačit přidáním třídy částečnou definici ProcessOnMenuCopyCommand MyDslClipboardCommandSet DslPackage projektu.

using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

partial class MyDslClipboardCommandSet
{
  /// <summary>
  /// Override ProcessOnMenuCopyCommand() to copy elements to the
  /// clipboard in different formats, or to perform additional tasks
  /// before or after copying – for example deselect the copied elements.
  /// </summary>
  protected override void ProcessOnMenuCopyCommand()
  {
    IList<ModelElement> selectedModelElements = this.SelectedElements;
    if (selectedModelElements.Count == 0) return;

    // System container for clipboard data.
    // The IDataObject can contain data in several formats.
    IDataObject dataObject = new DataObject();
      
    Bitmap bitmap = null; // For export to other programs.
    try
    {
      #region Create EGP for copying to a DSL.
      this.CopyModelElementsIntoElementGroupPrototype
                     (dataObject, selectedModelElements);
      #endregion
      
      #region Create bitmap for copying to another application. 
      // Find all the shapes associated with this selection:
      List<ShapeElement> shapes = new List<ShapeElement>(
        this.ResolveExportedShapesForClipboardImages
              (dataObject, selectedModelElements));

      bitmap = this.CreateBitmapForClipboard(shapes);
      if (bitmap != null)
      {
        dataObject.SetData(DataFormats.Bitmap, bitmap);
      }
      #endregion 
     
      // Add the data to the clipboard:
      Clipboard.SetDataObject(dataObject, true, 5, 100);
    }
    finally
    {
      // Dispose bitmap after SetDataObject:
      if (bitmap != null) bitmap.Dispose();
    }
  }
/// <summary>
/// Override this to customize the element group that is copied to the clipboard.
/// </summary>
protected override void CopyModelElementsIntoElementGroupPrototype(IDataObject dataObject, IList<ModelElement> selectedModelElements)
{
  return this.ElementOperations.Copy(dataObject, selectedModelElements);
}
}

Každý diagram byl singleton výskyt ElementOperations.Můžete zadat vlastní derivát.Tento soubor lze umístit do projektu DSL, by se chovají stejně jako kód, který přepíše:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.Modeling;
using Microsoft.VisualStudio.Modeling.Diagrams;

namespace Company.MyDsl
{
  partial class MyDslDiagram
  {
    /// <summary>
    /// Singleton ElementOperations attached to this diagram.
    /// </summary>
    public override DesignSurfaceElementOperations ElementOperations
    {
      get
      {
        if (this.elementOperations == null)
        {
          this.elementOperations = new MyElementOperations(this.Store as IServiceProvider, this);
        }
        return this.elementOperations;
      }
    }
    private MyElementOperations elementOperations = null;
  }

  // Our own version of ElementOperations so that we can override:
  public class MyElementOperations : DesignSurfaceElementOperations
  {
    public MyElementOperations(IServiceProvider serviceProvider, ElementOps1Diagram diagram)
      : base(serviceProvider, diagram)
    { }


     
    /// <summary>
    /// Copy elements to the clipboard data.
    /// Provides a hook for adding custom data.
    /// </summary>
    public override void Copy(System.Windows.Forms.IDataObject data, 
      ICollection<ModelElement> elements, 
      ClosureType closureType, 
      System.Drawing.PointF sourcePosition)
    {
      if (CanAddElementGroupFormat(elements, closureType))
      {
        AddElementGroupFormat(data, elements, closureType); 
      }

      // Override these to store additional data:
      if (CanAddCustomFormat(elements, closureType))
      {
        AddCustomFormat(data, elements, closureType, sourcePosition);
      }
    }
     
    
    protected override void AddElementGroupFormat(System.Windows.Forms.IDataObject data, ICollection<ModelElement> elements, ClosureType closureType)
    {
      // Add the selected elements and those implied by the propagate copy rules:
      ElementGroup elementGroup = this.CreateElementGroup(elements, closureType);

      // Mark all the elements that are not embedded under other elements:
      this.MarkRootElements(elementGroup, elements, closureType);

      // Store in the clipboard data:
      ElementGroupPrototype elementGroupPrototype = this.CreateElementGroupPrototype(elementGroup, elements, closureType);
      data.SetData(ElementGroupPrototype.DefaultDataFormatName, elementGroupPrototype);
    }

    /// <summary>
    /// Override this to store additional elements in the element group:
    /// </summary>
    protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup, ICollection<ModelElement> elements, ClosureType closureType)
    {
      ElementGroupPrototype prototype = new ElementGroupPrototype(this.Partition, elementGroup.RootElements, elementGroup);
      return prototype;
    }

    /// <summary>
    /// Create an element group from the given starting elements, using the 
    /// copy propagation rules specified in the DSL Definition.
    /// By default, this includes all the embedded descendants of the starting elements,
    /// and also includes reference links where both ends are already included.
    /// </summary>
    /// <param name="startElements">model elements to copy</param>
    /// <param name="closureType"></param>
    /// <returns></returns>
    protected override ElementGroup CreateElementGroup(ICollection<ModelElement> startElements, ClosureType closureType)
    {
      // ElementClosureWalker finds all the connected elements, 
      // according to the propagate copy rules specified in the DSL Definition:
      ElementClosureWalker walker = new ElementClosureWalker(this.Partition, 
        closureType, // Normally ClosureType.CopyClosure
        startElements, 
        true, // Do not load other models.
        null, // Optional list of domain roles not to traverse.
        true); // Include relationship links where both ends are already included.
      
      walker.Traverse(startElements);
      IList<ModelElement> closureList = walker.ClosureList;
      Dictionary<object, object> closureContext = walker.Context;

      // create a group for this closure
      ElementGroup group = new ElementGroup(this.Partition);
      group.AddRange(closureList, false);

      // create the element group prototype for the group
      foreach (object key in closureContext.Keys)
      {
        group.SourceContext.ContextInfo[key] = closureContext[key];
      }

      return group;
    }
  }
}

Viz také

Koncepty

Přizpůsobení vytvoření prvku a pohyb

Jak: Přidat ukazatel a přetažení

Přizpůsobení chování odstranění

Další zdroje

Vzorek: Vzorek okruhů VMSDK