ElementOperations Class

Provides common operations that act upon a collection of model elements.

Namespace:  Microsoft.VisualStudio.Modeling
Assembly:  Microsoft.VisualStudio.Modeling.Sdk (in Microsoft.VisualStudio.Modeling.Sdk.dll)

Syntax

'Declaration
Public Class ElementOperations
'Usage
Dim instance As ElementOperations
public class ElementOperations
public ref class ElementOperations
public class ElementOperations

Remarks

Derive from this class to create custom data formats for copy and paste operations. In your diagram class, override ElementOperations to return an instance of your ElementOperations subclass. You should return the same instance at every call.

To define your own ElementOperations

  1. In a new file in your DSL project, create a class that is derived from DesignSurfaceElementOperations.

  2. Add a partial class definition for your diagram class. The name of this class can be found in Dsl\GeneratedCode\Diagrams.cs.

    In the diagram class, override ElementOperations to return an instance of your ElementOperations subclass. You should return the same instance at every call.

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
  }

Receiving items dragged from other models

ElementOperations can also be used to define copy, move, deletion and drag-and-drop behavior.

Define two methods in your ElementOperations class:

  • CanMerge(ModelElement targetElement, System.Windows.Forms.IDataObject data) which determines whether the source element can be dragged onto the target shape, connector or diagram.

  • MergeElementGroupPrototype(ModelElement targetElement, ElementGroupPrototype sourcePrototype) which combines the source element into the target.

CanMerge()

[CanMerge()] is called to determine feedback that should be given to the user as the mouse moves across the diagram. The parameters to the method are the element over which the mouse is hovering, and data about the source from which the drag operation has been performed. The user can drag from anywhere on the screen. Therefore, the source object can be of many different types and can be serialized in different formats. If the source is a DSL or UML model, the data parameter is the serialization of an ElementGroupPrototype. Drag, copy and toolbox operations use ElementGroupPrototypes to represent fragments of models.

An Element Group Prototype can contain any number of elements and links. Element types can be identified by their GUIDs. The GUID is of the shape that was dragged, not the underlying model element. In following example, CanMerge() returns true if a class shape from a UML diagram is dragged onto this diagram.

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

This method is called when the user drops an element onto a diagram, a shape, or a connector. It should merge the dragged content into the target element. In this example, the code determines whether it recognizes the combination of target and prototype types; if so, the method converts the dragged elements into a prototype of the elements that should be added to the model. The base method is called to perform the merge, either of the converted or unconverted elements.

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

This example deals with UML class elements dragged from a UML class diagram. The DSL is not designed to store UML classes directly, but instead, we create a DSL element for each dragged UML class. This would be useful, for example, if the DSL is an instance diagram. The user could drag classes onto the diagram to create instances of those classes.

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

Inheritance Hierarchy

System.Object
  Microsoft.VisualStudio.Modeling.ElementOperations
    Microsoft.VisualStudio.Modeling.Diagrams.DesignSurfaceElementOperations

Thread Safety

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

See Also

Reference

ElementOperations Members

Microsoft.VisualStudio.Modeling Namespace

Change History

Date

History

Reason

Added more how-to.

Customer feedback.