Sdílet prostřednictvím


Přizpůsobení chování kopírování

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

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

Chcete-li povolit, kopírování, nastavte povolit kopírování vkládání vlastnost Editor uzel v Průzkumníku DSL.

Ve výchozím nastavení pokud uživatel zkopíruje elementy do schránky následující prvky také zkopírovány:

  • Vložený následníků vybraných elementů.(To znamená, elementy, které jsou cíle vnoření vztahy, které jsou, která byla vytvořena na zkopíruje elementy.)

  • Odkazy vztah mezi zkopírovaných elementy.

Toto pravidlo aplikuje rekurzivně zkopírovaných elementy a odkazy.

Zkopírované a vložené prvky

Zkopírované elementy a odkazy jsou serializován a uložené do ElementGroupPrototype (EGP), která je umístěna do schránky.

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

Uživatele můžete vložit zkopírovaný prvků na cíl, který může přijmout elementy souladu s definicí DSL.V DSL, vygenerovaná z této šablony součásti řešení, například uživatele můžete vložit porty do komponenty, ale není do diagramu; a můžete vložit komponent do diagramu, ale ne na další součásti.

Přizpůsobení kopírování a vkládání chování

Další informace o přizpůsobení modelu s použitím programového kódu, naleznete v části Navigace v modelu a aktualizace modelu v kódu programu.

  • Povolit nebo zakázat kopírovat, vyjmout a vložit.
    V Průzkumníku DSL nastavena povolit kopírování vkládání vlastnost Editor uzlu.

  • Zkopírujte odkazy pro stejný cíl. Můžete například mít pole zkopírované komentáře propojí stejného elementu předmětu.
    Nastavte šíří kopie vlastnost role, kterou chcete šířit kopii pro odkaz pouze.Další informace naleznete v tématu přizpůsobení chování kopie odkaz.

  • Zkopírujte odkazované elementy. Například při kopírování nového elementu kopie všech polí propojené komentář jsou také provedeno.
    Nastavte šíří kopie vlastnost role, kterou chcete šířit kopie na odkaz a s opačným role player.Další informace naleznete v tématu přizpůsobení chování kopie odkaz.

  • Zkopírováním a vložením rychle duplicitní elementy. Za normálních okolností je stále vybrána položka, kterou jste právě zkopírovali, a nelze vložit stejný typ elementu na něj.
    Přidejte direktivu sloučit elementu na třídu domény a nastavte ji na vpřed sloučení 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í a přesunutí elementu.

    -nebo-

    Před vložením prvků, přepsáním vyberte diagramu ClipboardCommandSet.ProcessOnPasteCommand().Přidejte tento kód v souboru vlastní v projektu DslPackage:

    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é cílové. Například vloženého pole komentáře do elementu odkaz provedeno mezi nimi.
    Přidejte direktivu sloučení Element cílová třída domény a nastavte ji zpracovat sloučení 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í a přesunutí elementu.

    -nebo-

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

  • Přizpůsobit formáty, ve kterých lze kopírovat elementy pro externí aplikace – například chcete přidat do formuláře rastrového obrázku ohraničení.
    Přepsání MyDslClipboardCommandSet.ProcessOnMenuCopyCommand() v DslPackage projektu.

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

  • Zachovat rozvržení tvar pomocí Kopírovat a vložit.
    Pokud uživatel zkopíruje více tvarů, můžete v případě, že jsou vloženy zachovat jejich relativní polohy.Tento postup je ukázáno v příkladu na adrese VMSDK: okruhů ukázky.

    K dosažení tohoto efekt, přidejte do zkopírovaných ElementGroupPrototype tvary a konektory.Nejlépe vyhovuje metodu pro přepsání je ElementOperations.CreateElementGroupPrototype().Chcete-li to provést, přidejte do projektu Dsl následující kód:

    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žte tvary do vybraného umístění, jako je například aktuální pozici kurzoru.
    Pokud uživatel zkopíruje více tvarů, můžete v případě, že jsou vloženy zachovat jejich relativní polohy.Tento postup je ukázáno v příkladu na adrese VMSDK: okruhů ukázky.

    K dosažení tohoto efekt, přepište ClipboardCommandSet.ProcessOnMenuPasteCommand() pro použití verze konkrétní umístění ElementOperations.Merge().Chcete-li to provést, přidejte do projektu DslPackage následující kód:

    
    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 myší elementy.
    Další informace naleznete v tématu Postupy: Přidání obslužné rutiny operace přetažení myší.

Přizpůsobení chování kopie odkaz

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

Šíří vlastnost kopírování role domény

Existují tři hodnoty:

  • Nešířily kopie

  • Šířit kopii pro odkaz pouze - vloženého skupině novou kopii tento odkaz bude odkazovat na existující element na druhém konci odkazu.

  • Šířit kopii pro odkaz a opačným role player - zkopírovaných skupina obsahuje kopii elementu na druhém konci odkazu.

Platnost kopírování s PropagateCopyToLinkOnly

Změny, které jste provedli bude mít vliv na elementy a obrázek, který bude zkopírován.

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

Řady aspektů chování DSL s ohledem na Kopírovat, vložit, vytvoření a odstranění objektů, které se řídí instance ElementOperations který je připojen k diagramu.Můžete upravovat své DSL chování odvozením vlastní třídy z ElementOperations a přepsání ElementOperations vlastnost vaší třídy diagramu.

Tip

Další informace o přizpůsobení modelu s použitím programového kódu, naleznete v části Navigace v modelu a aktualizace modelu v kódu programu.

Sekvenční diagram pro kopírováníSekvenční diagram vložení

Chcete-li definovat vlastní ElementOperations

  1. Do nového souboru v projektu DSL, vytvořte třídu, která je odvozena z DesignSurfaceElementOperations.

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

    Ve třídě diagramu přepsání ElementOperations vrátit instanci vaše podtřídy ElementOperations.By měl vrátit stejné instance v každém volání.

Přidejte tento kód v souboru vlastního kódu v projektu DslPackage:

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řijímá položky přetáhli od jiných modelů

ElementOperations lze také definovat chování kopírovat, přesunout, odstranění a přetahováním myší.Příklad zde uvedeny jako ukázky použití ElementOperations, definuje vlastní chování přetahováním myší.K tomuto účelu může však zvážit alternativní metody uvedené v Postupy: Přidání obslužné rutiny operace přetažení myší, což 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ého prvku lze přetáhnout do cílového tvaru, konektoru nebo diagramu.

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

CanMerge()

CanMerge()je volána k určení, zpětnou vazbu, která by měla být poskytnuta uživateli jako pohybu myši v rámci diagramu.Parametry metody jsou elementu, jehož prostřednictvím umístění ukazatele myši a data o zdroji, ze kterého byla provedena operace přetažení.Uživatele můžete přetáhnout z libovolného místa 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 modelu, parametr data je serializace ElementGroupPrototype.Operace přetahování, kopírování a sadu nástrojů, které používají ElementGroupPrototypes k reprezentování fragmenty modelů.

Prototypu Element skupiny mohou obsahovat libovolný počet elementů a odkazy.Typy elementů lze identifikovat podle identifikátorů GUID.Identifikátor GUID je obrazec, který byl přetáhli, nikoli základní prvek modelu.V následujícím příkladu CanMerge() vrací hodnotu true, pokud je třída tvar z diagramu UML přetáhli 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 přesune element do diagramu, tvar nebo konektoru.Ji by měl sloučit taženou obsah do cílového elementu.V tomto příkladu kód určuje, zda rozpozná kombinaci typů cíl a prototypu; Pokud ano, tato metoda převede taženou elementy do prototypu elementů, které mají být přidány do modelu.Základní metoda je volána k provedení sloučení, buď elementů převedený nebo nepřevedené.

    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á elementy třídy UML přetažení z diagramu UML třídy.DSL není určen k uložení třídy UML přímo, ale namísto toho doporučujeme vytvořit element DSL pro každou třídu taženou UML.To bude užitečné v případech, například když DSL je diagramu instance.Uživatel může přetažením třídy diagramu k vytváření instancí těchto tříd.

    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í kopie chování

Kód v této části ukazuje a změnit tak kopírování chování lze přepsat metody, které vám mohou.Abychom vám v tématu how to dosáhnout vlastní vlastní nastavení, v této části ukazuje kód, který přepíše metody zapojené do kopírování, ale nedojde ke změně standardní chování.

Když uživatel stiskne klávesu CTRL + C nebo používá nabídky příkaz Copy, metoda ProcessOnMenuCopyCommand je volána.Uvidíte, jak toto nastavení DslPackage\Generated Code\CommandSet.cs.Další informace o tom, jak jsou příkazy nastavit, naleznete v části Postupy: Přidání příkazu do místní nabídky.

Můžete přepsat ProcessOnMenuCopyCommand přidáním definice dílčí třídu MyDslClipboardCommandSet v 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ů má instanci jednotlivý prvek ElementOperations.Můžete zadat vlastní odvozených.Tento soubor, který je možné použít v 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í a přesunutí elementu

Postupy: Přidání obslužné rutiny operace přetažení myší

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

Další zdroje

Ukázka: VMSDK okruhů ukázky