Hi,

I am building a 'shape editor' which looks very similar to the Visual Studio form designer. I have a Toolbox control that holds a few 'Shapes' (such as RectangleShape, EllipseShape, TriangleShape, etc) which the user should be able to drag to the design view ("Canvas") in any MDI form. The Toolbox control is just a TreeView except that I add ToolboxItems to it (which are inherited TreeNodes).

This dragging however does not seem to work...

The ToolboxItem (the nodes in the TreeView Toolbox) have a property ShapeType (Type) which holds the Type of the shape they represent.
vb.net Code:
  1. Public Class ToolboxItem
  2.    Inherits TreeNode
  3.  
  4.    Public Property ShapeType As Type
  5.  
  6. End Class
When adding ToolboxItems I set this type:
vb.net Code:
  1. toolbox.AddItem(New ToolboxItem("Rectangle", GetType(RectangleShape))
  2. toolbox.AddItem(New ToolboxItem("Ellipse", GetType(EllipseShape))
  3. toolbox.AddItem(New ToolboxItem("Triangle", GetType(TriangleShape))

Now, when I initiate a DragDrop operation I pass this ShapeType as the data:
vb.net Code:
  1. Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
  2.     If e.Button = System.Windows.Forms.MouseButtons.Left Then
  3.         If dragRectangle <> Rectangle.Empty AndAlso Not dragRectangle.Contains(e.Location) Then
  4.             Dim selItem = TryCast(Me.GetNodeAt(e.Location), ToolboxItem)
  5.             If selItem IsNot Nothing AndAlso selItem.Level = 1 Then
  6.                 Me.DoDragDrop(selItem.ShapeType, DragDropEffects.Move)
  7.             End If
  8.         End If
  9.     End If
  10.     MyBase.OnMouseMove(e)
  11. End Sub
The 'dragRectangle' check is to ensure that the mouse has moved enough to initiate a drag drop operation (SystemInformation.DragSize).

In the 'document' form that contains the Canvas (where the shapes live), I handle the DragEnter and DragDrop events of the Canvas. I get the data of type System.Type, and if it is not nothing I add a new shape at the current location, using Activator.CreateInstance to create the shape from the type that is dragged onto the canvas:
vb.net Code:
  1. Private Sub canvas_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs) Handles canvas.DragDrop
  2.     Dim data = e.Data.GetData(GetType(System.Type))
  3.     If data IsNot Nothing Then
  4.         Dim pt = Me.PointToClient(New Point(e.X, e.Y))
  5.         Dim shape = DirectCast(Activator.CreateInstance(DirectCast(data, Type), pt), Shape)
  6.         canvas.Shapes.Add(shape)
  7.     End If
  8. End Sub
  9.  
  10. Private Sub canvas_DragEnter(ByVal sender As Object, ByVal e As DragEventArgs)
  11.     Dim data = e.Data.GetData(GetType(System.Type))
  12.     If data IsNot Nothing Then
  13.         e.Effect = DragDropEffects.Move
  14.     Else
  15.         e.Effect = DragDropEffects.None
  16.     End If
  17. End Sub

However... It doesn't work. When I drag a shape from the toolbox onto the canvas the mouse turns into the 'cannot drag' icon (well I've no idea what it's called) and when I release the mouse nothing happens. By debugging I can see that 'data' is Nothing...

I must be doing something wrong but I cannot figure it out. I am clearly passing a Type to the 'data' parameter of the DoDragDrop method... I think I'm tripping over the GetType(Type)... That makes little sense to me, can you even do that?

If not, how else should I handle this?

Thanks!