Drag and Drop Support
This article will get you familiar with the RadDiagram drag/drop support.
The RadDiagram framework supports drag/drop operations out-of-the-box for a list of scenarios. For every scenario outside that list, it allows you to easily define your custom drop logic.
Enable Drag/Drop
To allow drag and drop functionality in the RadDiagram, set the AllowDrop attribute to True.
The drag and drop behavior can be enabled in the code-behind as well. In order to do that you need to set the AllowDrop property of an instance of the RadDiagram class to True.
Please note that the RadDiagram AllowDrop property is set to True by default.
Automatically Supported Drop Operations
The RadDiagram framework allows you to drop:
-
Image Files - You can just drag and drop onto the Diagramming surface any image file from the following list of supported formats:
- JPEG(*.jpg)
PNG(*.png)
BMP(*.bmp)
- TIFF(*.tiff)
- GIF(*.gif)
Text Files - You can drag .TXT files directly onto the diagramming surface to create text shapes. The operation will take the content of the .TXT file and will place it as a content of a text shape.
Text - You can drag chunks of text from your documents onto the diagramming surface directly.
Serialization XML string - You can drag the serialization xml string of a RadDiagram native element. You can find more information on how to serialize the RadDiagram native elements in an XML string, please have a look at the Serialization topic.
Custom Drop Operations
By default, the RadDiagram can handle drop operations out-of-the-box as long as the dropped data represents a serialized RadDiagramItem. This is why if you create an ItemsControl containing a list of RadDiagramItems, you will only have to set the dragged data to represent a serialized RadDiagramItem. However, if you have an ItemsControl displaying custom business data, then you will have to manually configure how to drag and drop the business items.
Please note that the examples in this tutorial are showcasing Telerik Windows8 theme. In the Setting a Theme article you can find more information on how to set an application-wide theme.
Dragging RadDiagramShapes from an ItemsControl
Let's examine a scenario where you create a ListBox populated with RadDiagramShapes and a RadDiagram component next to it:
In order to allow a drag of a ListBoxItem, you need to apply a style that makes the ListBoxItems draggable:
In this scenario, the RadDiagram instance can automatically handle the drop of the RadDiagramShapes as long as they are serialized. In order to serialize them you need to create a handler for the ListBox DragDropManager.DragInitialized event:
In the above example you can drag an entire ListBoxItem but you may need to only drag the RadDiagramShape contained within the item. In that case, you will have to create a custom style targeting the RadDiagramShapes within the ListBox control. Please note that you have to apply this style only on those shapes defined within the ListBox control.
And you will also have to slightly modify the OnDragInitialize() implementation as it now looks for a ListBoxItem as its OriginalSource. Once the ListBoxItems aren't marked as draggable and only the shapes are defined as such, the OriginalSource of the event will be a shape instance.
Dragging business data from an ItemsControl
In MVVM scenarios, the business data is usually displayed within ItemsControls. And if you need to drag the items of these controls and drop them on a diagramming surface, you need to customize the drag/drop operations on both sides - in the source of the drag and in the targeted RadDiagram.
For the purpose of this tutorial, we will examine a sample scenario describing how to implement a drag operation from a ListBox control to a RadDiagram. Our goal would be to create a RadDiagramShape to wrap the dragged data.
-
First, let's create a sample data source for the ListBox:
-
Now that we have defined our MainViewModel class, we can use it as a DataContext of our main view:
The local alias points to the namespace where the MainViewModel class is defined.
-
Next we can set up our layout. We will need a ListBox definition and a RadDiagram definition. Also, as we have to allow drag/drop operations between them, we need to apply the DragDropManager.AllowCapturedDrag attached property on the ListBoxItems and we can set the AllowDrop property to True in the RadDiagram definition.
-
As the layout is all in place, we can go ahead and start implementing our dragging logic. For that purpose, we need to decide how to interpret the dragged items and what to pass as the Data of the drag operation. We can implement this logic in the DragInitialize event handler:
And the ApplicationTemplate definition should be in the Resources section of our view:
You can find more information about the features and events of the DragDropManager in its documentation.
-
Finally, we need to customize the RadDiagram drop logic to create a RadDiagramShape to wrap the dragged data. We can also apply a Position property on the RadDiagramShape to reflect the exact position of the mouse during the drop.
The easiest way to get the position of the mouse in the Drop event handler is through the DragEventsArgs GetPosition() method. However, as RadDiagram supports different scaling operations (pan, zoom), you need to get the coordinates of the drop target point in the context of the RadDiagram. For that purpose you can use the RadDiagram GetTransformedPoint extension method. It takes a point, applies any pan and/or zoom settings defined by the RadDiagram current state and returns a point, transformed in the context of the diagram. This allows you to correctly position a RadDiagramItem in a panned or zoomed diagramming surface.
Please note that the GetTransformedPoint() extension method is defined in the Telerik.Windows.Controls.Diagrams namespace so you need to include this namespace in your class definition before getting advantage of the method.
Please note that we've set the Position property of the RadDiagramShape
Please note that you have to handle the Drop event in order to stop its default logic and implement your own instead.