Поделиться через


Настройка функции копирования

В доменном языке DSL, созданном с Visual Studio Пакет SDK для визуализации данных и моделирования можно изменять, что происходит, когда пользователь копирует и вставляет элементы.

Стандартная копировать и вставлять расширения функциональности

Чтобы включить копирование, установите Включите вставить копии свойство Редактор узел в обозревателе DSL.

По умолчанию, когда пользователь копирует элементы в буфер обмена также копируются следующие элементы:

  • Внедренные потомки выбранных элементов.(То есть элементы, которые целевые объекты внедрение связей, источником на скопированных элементов.)

  • Ссылки на связи между скопированными элементами.

Это правило применяется рекурсивно к копированию элементам и ссылкам.

Скопированные и вставленные элементы

Копируемые элементы, и связи, сериализуются и сохраняются в ElementGroupPrototype (EGP), который помещается в буфер обмена.

Образ скопированных элементов также помещается в буфер обмена.Это позволяет пользователю вставить в другие приложения машинное слово.

Пользователь может вставлять элементы, скопированные на целевой объект, который может принимать элементы согласно определению DSL.Например, в DSL создаваемый из шаблона решения компонентов, пользователь может вставить портов на компоненты, но не на схему. и удалось вставить компоненты на схему, но не на другие компоненты.

Настраивать копировать и вставлять расширения функциональности

Дополнительные сведения о настройке модели с помощью программного кода, см. в разделе Перемещение по модели и обновление модели в коде программы.

  • Включение или отключение копию, вырежьте и вставьте.
    в обозревателе DSL, установите Включите вставить копии свойство Редактор узел.

  • Связи копии к тому же целевому объекту. Например, иметь скопированный окно комментарий связанное на один и тот же элемент раздела.
    Установка Передает копии свойство роли к Propagate копия только для связывания.Дополнительные сведения см. в разделе Настройка расширения функциональности копии ссылки.

  • Элементы связанные копии. Например, при копировании новый элемент копии всех связанных окон комментария выполняются.
    Установка Передает копии свойство роли к Propagate копии для связывания и противоположная роль проигрывателя.Дополнительные сведения см. в разделе Настройка расширения функциональности копии ссылки.

  • Быстро повторяющиеся элементы, копировать и вставлять. Как правило, он просто которые были скопированы все еще установлен, и нельзя вставить один и тот же тип элемента на него.
    Добавьте директиву слияния элемента доменному классу и установите ее для переадресованы слияния на родительский класс.Это оказывает такое же влияние на операциях перетаскивания.Дополнительные сведения см. в разделе Настройка создания и перемещения элементов.

    - или -

    Выберите схему перед вставить элементы, путем переопределения ClipboardCommandSet.ProcessOnPasteCommand().Добавьте этот код в пользовательском файле проекта 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);
      }
    } }
    
  • Создание дополнительных связей, когда вставляет пользователя на выбранный целевой объект. Например, когда окно " комментарий вставленно на элемент, связь создается между ними.
    Добавьте директиву слияния элементов к классу доменному целевого объекта и установите ее для обработки слияние с добавление ссылки.Это оказывает такое же влияние на операциях перетаскивания.Дополнительные сведения см. в разделе Настройка создания и перемещения элементов.

    - или -

    Переопределенный ClipboardCommandSet.ProcessOnPasteCommand() создание дополнительных связей после вызова метода базовый метод.

  • Настройка форматы, в которых элементы можно скопировать для внешних приложений - например, чтобы добавить границу к форме растрового изображения.
    Переопределенный MyDslClipboardCommandSet.ProcessOnMenuCopyCommand() в проекте DslPackage.

  • Как настраивать элементы копируются в буфер обмена командой копии, но не в операции перетаскивания.
    Переопределенный MyDslClipboardCommandSet.CopyModelElementsIntoElementGroupPrototype() в проекте DslPackage.

  • Макет формы сохраняется посредством копировать и вставить.
    Когда пользователь копирует несколько фигур, можно сохранить их относительные позиции, когда они вставлены.Этот метод показан пример в VMSDK: Образец принципиальных схем.

    Чтобы этого добиться, добавление фигур и соединителей на копируемый ElementGroupPrototype.Самый удобный метод для переопределения ElementOperations.CreateElementGroupPrototype ().Чтобы сделать это, добавьте следующий код к проекту Dsl:

    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;
    }
    
  • Вставьте фигуры в выбранном местоположении, как текущая позиция курсора.
    Когда пользователь копирует несколько фигур, можно сохранить их относительные позиции, когда они вставлены.Этот метод показан пример в VMSDK: Образец принципиальных схем.

    Чтобы этого добиться, нужно переопределить ClipboardCommandSet.ProcessOnMenuPasteCommand() использовать версию место хранения-специфического ElementOperations.Merge().Для этого добавьте следующий код в проекте DslPackage:

    
    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();
              }
            }
          }
        }
      }
    
  • Предоставьте пользователю перетаскивание элементов.
    Дополнительные сведения см. в разделе Практическое руководство. Добавление обработчика перетаскивания.

Настройка расширения функциональности копии ссылки

Когда пользователь копирует элемент стандартной функциональности, что все внедренные элементы также копируются.Можно изменить стандартную расширения функциональности копирования.В определении DSL, выберите роль на одной стороне связи и в наборе окна свойств Передает копии значения.

Распространяет свойство копирования роли домена

3 Значений:

  • Не propagate копии

  • Propagate копии для связывания только - если группа будет вставленна, новая копия данной связи будет ссылаться на существующий элемент в другом конце связи.

  • Propagate копии для связывания и противоположная роль проигрывателя - скопированную группа содержит копию элемента в другом конце связи.

Результат копирования с использованием PropagateCopyToLinkOnly

Изменения повлияют на и элементы и образ, который копируется.

Программирование копировать и вставлять расширения функциональности

Многие аспекты расширения функциональности DSL, касающиеся копии вставить, создания и удаления объектов управлены экземпляром ElementOperations будет привязана к схеме.Можно изменить поведение конкретного DSL путем наследования собственный класс из ElementOperations и переопределять ElementOperations свойство класса схемы.

СоветСовет

Дополнительные сведения о настройке модели с помощью программного кода, см. в разделе Перемещение по модели и обновление модели в коде программы.

Схема последовательностей для операции копированияСхема последовательностей операции вставки

Указать собственное ElementOperations

  1. В новом файле в проекте DSL, создайте класс, производный от DesignSurfaceElementOperations.

  2. Добавьте определение разделяемого класса для класса схемы.Имя этого класса можно найти в Dsl\GeneratedCode\Diagrams.cs.

    В классе схемы, переопределение ElementOperations возвращать экземпляр ElementOperations конкретного подкласса.Вы должны возвращать один и тот же экземпляр при каждом вызове.

Добавьте этот код в файле пользовательского кода в проекте 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
  }

Получение перетащенные элементы из других моделей

ElementOperations может также использоваться для определения копирование, перемещение, удаление и расширения функциональности перетаскивания.В качестве демонстрации использования ElementOperations, примере заданный здесь задает пользовательские расширения функциональности перетаскивания.Однако для этой целью можно рассмотреть альтернативный подход описано в пределах Практическое руководство. Добавление обработчика перетаскивания, который более является расширяемым.

Укажите 2 метода в классе ElementOperations:

  • CanMerge(ModelElement targetElement, System.Windows.Forms.IDataObject data) что определяет, является ли элемент источника можно перетащить на форму, соединитель или схемы целевого объекта.

  • MergeElementGroupPrototype(ModelElement targetElement, ElementGroupPrototype sourcePrototype) объединяет элемент, источника на целевой объект.

Ff521398.collapse_all(ru-ru,VS.110).gifCanMerge ()

[CanMerge()] вызывается для указания отзыв, следует предоставлять пользователю по мере того, как указатель мыши перемещается в схему.Параметры метода элемент, по которому мыши изменяется, а также сведения об источнике, из которого была выполнена операция перетаскивания.Пользователь может перетаскивать из любого места на экране.Следовательно, исходный объект может иметь много различных типов и может быть сериализован в различных форматах.Если источник модель UML или DSL, то параметр данных сериализация ElementGroupPrototype.Перетащите, копирование и использование ElementGroupPrototypes операций области элементов представления фрагменты моделей.

Заполнитель группы элементов может содержать любое число элементов и связей.Типы элементов могут быть определены их GUID.Идентификатор GUID фигуры, которая была перетащенна, не базового элемента модели.В следующем примере CanMerge() возвращает значение true, если фигура класса из uml-схемы перетащенна на эту схему.

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 ()

Этот метод вызывается, когда пользователь удаляет элемент на схеме, фигуры или соединитель.Он должен выполнить слияние перетащенное содержимое в элемент целевого объекта.В этом примере код определяет, распознает ли типы целевого объекта и местозаполнитель сочетание; если это так, метод преобразует перетащенные элементы в прототип элементов, которые должны быть добавлены к модели.Вызывается базовый метод, чтобы выполнить слияние или преобразования или unconverted элементов.

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

В этом примере имеет дело с элементами классов UML перетащенные из uml-схемы классов.DSL не предназначен для хранения uml-классы напрямую, но вместо этого создается элемент DSL для каждого перетаскиваемого класса UML.Это было бы полезно, например, если DSL схема экземпляра.Пользователь может перетащить на схему классов для создания экземпляров этих классов.

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

Реакция на событие стандартной копии

Код в этом разделе показывает, что методы, которые могут можно переопределить, чтобы изменить расширение функциональности копирования.Чтобы помочь понять, как добиться собственных настроек в этом разделе приведен код, который переопределяет методы, участвующие в копировании, но не изменяет стандартной функциональности.

При нажатии пользователем клавиши CTRL+C или использует команду меню копирования, метод ProcessOnMenuCopyCommand вызывает.Можно видеть, как это установка in DslPackage\Generated Code\CommandSet.cs.Дополнительные сведения о том, как команды программы установки см. в разделе Практическое руководство. Добавление команды в контекстное меню.

Можно переопределить ProcessOnMenuCopyCommand, добавляя определение разделяемого класса MyDslClipboardCommandSet в проекте DslPackage.

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

Каждая схема имеет одноэлементный экземпляр ElementOperations.Можно указать собственное производный.Этот файл, который можно поместить в проекте DSL, поступал бы эти же, как код, он переопределяет:

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

См. также

Основные понятия

Настройка создания и перемещения элементов

Практическое руководство. Добавление обработчика перетаскивания

Настройка функции удаления

Другие ресурсы

Пример: Образец принципиальных схем VMSDK