Silverlight Drag and Drop API
Introduction
Drag and drop is a common UX paradigm and a top requested feature. In Silverlight 4 Beta, we introduced a basic set of API to enable the most common scenario of dragging pictures files and dropping them to Silverlight applications, and we designed the API to allow us to expose more drag and drop functionalities down the road without API change, hopefully.
API
Below is the core of the new API:
namespace System.Windows
{
public abstract class UIElement : DependencyObject
{
// Fields
public static readonly DependencyProperty AllowDropProperty;
// Events
public event DragEventHandler DragEnter;
public event DragEventHandler DragLeave;
public event DragEventHandler DragOver;
public event DragEventHandler Drop;
// Properties
public bool AllowDrop { get; set; }
}
public delegate void DragEventHandler(object sender, DragEventArgs e);
public sealed class DragEventArgs : RoutedEventArgs
{
// Methods
public Point GetPosition(UIElement relativeTo);
// Properties
public IDataObject Data { [SecuritySafeCritical] get; }
public bool Handled { get; set; }
}
}
namespace System.Windows.Controls
{
public abstract class Control : FrameworkElement
{
protected virtual void OnDragEnter(DragEventArgs e);
protected virtual void OnDragLeave(DragEventArgs e);
protected virtual void OnDragOver(DragEventArgs e);
protected virtual void OnDrop(DragEventArgs e);
}
}
- AllowDrop: this is dependency property, indicating whether an element is a drop target.
- DragEnter, DragLeave, DragOver & Drop: these are routed events. They bubble up, and fire only on elements with AllowDrop set to true.
- OnDragEnter, OnDragLeave, OnDragOver & OnDrop: these are protected virtual functions for subclasses to override.
- DragEventArgs: this class allows drop target event handlers or method overrides to access the data being dragged or dropped.
Usage
There are primarily two ways to use Silverlight’s drag and drop API:
- Silverlight applications can handle those drop target events and process the files dropped in the event handlers.
- Silverlight controls can override those drop target virtual functions to process the data being dragged and dropped, and enable themselves to be drop targets.
Limitations
The drag and drop functionality shipped in Silverlight 4 Beta only enables the most common scenario: Silverlight plugin as a file drop target. Please notice the following limitations with current implementation:
- there is no drop source support (QueryContinueDrag & GiveFeedback).
- there is no DragDropEffects or DragDropKeyStates in DragEventArgs.
- there is no visual for the dragged object or DragDropEffects.
- only file drag and drop is supported:
- all drop target events fire only when files are being dragged and dropped.
- IDataObject, DataObject and DragEventArgs.Data support only one format: “FileDrop”, and the data is of type FileInfo[].
- most of IDataObject methods throw NotImplementedException.
- for drag and drop to work on Windows, Silverlight plugin must be windowed. In another word, if <param name="windowless" value="true"/> is specified, drop events won’t fire.
- since Silverlight plugin on Mac is always windowless, you need to hook up JavaScript drop events to trigger Silverlight drop events. In another word, if you want your Silverlight application to support file drop on Mac as well as Windows, you will need to add following script and Silverlight plugin attributes to the hosting html or aspx page:
<!-- add following script before end of HEAD tag -->
<script type="text/javascript">
function handleDragEnter(oEvent) {
// Prevent default operations
oEvent.preventDefault();
var flag = silverlightControl.dragEnter(oEvent);
// If we handled it successfully then stop propagation of the event
if (flag)
oEvent.stopPropagation();
}
function handleDragLeave(oEvent) {
// Prevent default operations
oEvent.preventDefault();
var flag = silverlightControl.dragLeave(oEvent);
// If we handled it successfully then stop propagation of the event
if (flag)
oEvent.stopPropagation();
}
function handleDragOver(oEvent) {
// Prevent default operations
oEvent.preventDefault();
var flag = silverlightControl.dragOver(oEvent);
// If we handled it successfully then stop propagation of the event
if (flag)
oEvent.stopPropagation();
}
function handleDropEvent(oEvent) {
// Prevent default operations
oEvent.preventDefault();
var flag = silverlightControl.dragDrop(oEvent);
// If we handled it successfully then stop propagation of the event
if (flag)
oEvent.stopPropagation();
}
</script>
<!-- use JavaScript drop target events to trigger Silverlight's drop target events -->
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"
id="silverlightControl" ondragenter="handleDragEnter(event)" ondragover="handleDragOver(event)"
ondragleave="handleDragLeave(event)" ondrop="handleDropEvent(event)" > - DragEventArgs.Data is only accessible in Drop event. Accessing DragEventArgs.Data in DragEnter, DragOver and DragLeave may cause SecurityException. And accessing Directory, DirectoryName or FullName property of the FileInfo object from DragEventArgs.Data may cause ArgumentNullException.
Demo App
Below is a demo app:
- the top left nested grids use drop target event handler to display DragEventArgs info.
- the top right nested grids contain an ImageDropTarget user control, which overrides OnDrop method to render the dropped file if it is an image.
- the bottom listbox shows the sequence of drop target events, their bubbling up, and DragEventArgs info.
you can find the complete source here.
Feedback
While we are excited to add drag and drop to Silverlight, we know there are a lot to finish/improve, and what we released is just a Beta. As always, your feedback is highly appreciated, and will be used as an important data point to help us prioritize the work. Thanks!








@David Leisner
Hi David,
Yes, the behavior is pretty much the same in SL4 RTM: user will see the standard cursor change at plugin level, ie, if there is one control with AllDrop set to true, the whole plugin will display the allow drop cursor; but it is not control specific, and it is not customizable, ie, cursor won’t change for controls with AllDrop set to false, and there is no DragDropEffects to set in DragEventArgs. We may implement more DnD functionalities in future releases.
Thanks,
-Ning
Thank you for this extremely useful and easy-to-implement feature!
Question: in your original article you said that in the Silverlight 4 Beta “there is no visual for the dragged object or DragDropEffects.”
Is this also the case in the final Silverlight 4 release?
When dragging an image from Windows Explorer to a Silverlight ListBox, it will be extremely useful to customize the cursor appearance, and also have a different style cursor depending upon whether the target element has AllowDrop enabled or not.
Thanks!
Hi, thank you for sample code.
Hi,
is it possible to prevent the DataGridDragDropTarget from starting a drag-action?
What I whant is to use one DataGrid only as DragSource and another one only as DropTarget. And the DropTarget-only-DataGrid should not show this “StartDragShadow” when pressing and moving the mouse over an item.
Thanks!
Steven
@Rudy
I also want to know.thank you!
regards
silverlight
@Rudy
Please see my other replies. The Silverlight Toolkit already has ListBoxDragDropTarget, so you can drag from ListBox. You do need to implement your own Canvas drag drop target container, for now.
@GB
Right now SL4 runtime only supports SL plugin as a file drop target, and only exposes drop target properties (AllDrop) and events (DragEnter/Move/Leave, Drop), but not drag source events (GiveFeedback, QueryContinueDrag). It is not fully extensible via IDataObject either. If you can’t wait, your best chance for now is to look at the toolkit implementation, which allows drag and drop to and from DataGrid within SL plugin. The code is in DataGridDragDropTarget.cs under source\Controls.Data.Toolkit project. Thanks.
hi, i want to know how to implement to drag&drop on datagrid?
I would like to know if there are any way to implement drag & drop objects (icons) from list box to canvas?
Regards
Rudy
@Brice Prunier
Yes. Jafar has implemented almost complete, WPF compatible, drag and drop functionality for both Silverlight 3 and Silverlight 4. It is shipped as part of Silverlight Toolkit. I highly recommend checking out his blog posts for more information.
Please notice a key differences between the two drag and drop implementations: the Toolkit version is implemented on top of runtime, so it requires a *DragDropTarget container, and works only between elements within a Silverlight plugin control. The Toolkit implementation leverages runtime drag and drop API when it can, like in Silverlight 4 Toolkit, Microsoft.Windows.DragDrop.AllowDrop uses UIElement.AllowDrop property. While the runtime exposes drop target events for all UIElement, the Toolkit implementation already handles those events for important controls like DataGrid, ListBox and TreeView, so it is really easy to use. We’ve made sure the APIs are as compatible as possible, so people can use both together for now, and migrate to runtime implementation rather easily as runtime exposes more drag and drop functionalities. This is also the general approach of Silverlight Toolkit, as I called out in earlier post Silverlight Controls.
SL4 Toolkit (System.Windows.Controls.Toolkit) provides more higher level DragDrop implementations for intra Silverligth Drag & Drop.
Not all cases are currently supported by SL 4 Toolkit but you can easely create your own from the abstract class DragDropTarget.
regards