Drag & Drop

Drag & drop data and files concepts.

In Wisej every control supports drag & drop operations, which is different from dragging (moving) the control itself. Drag & drop means that your application allows the user to drag data from one control to another.

For example, you may want to drag a row from a grid to an input field, or within the grid to change its position, or you may want to drag a node from a tree control to another.

Drag & drop in Wisej works exactly the same as in a desktop application: set AllowDrag on the control that should initiate the drag operation and set AllowDrop on the control that can receive the dropped data.

When the user starts dragging, the control will fire the DragStart event. You must handle this event and call the DoDragDrop() method, otherwise the drag operation doesn't start.

private void dataGridView1_DragStart(object sender, EventArgs e)
{
    this.dataGridView1.DoDragDrop(
        this.dataGridView1.SelectedRows.ToArray(),
        DragDropEffects.Copy | DragDropEffects.Move);
}

A common mistake is to call this.DoDragDrop() instead of this.[control].DoDragDrop() when handling the event in a parent container. Make sure to call DoDragDrop() on the correct target.

The code above starts a drag operation using an array of selected row indexes as the payload, the user is basically dragging an array of integers. In addition to the payload, the call above also indicates that the drag operation allows only 2 effects: Copy and Move. Conceptually it means that the payload can only be copied or moved. Another option is Link.

Now you need to handle the dropping side, on the controls that can accept the dragged payload. This is done using either DragEnter or DragOver or both.

The code below activates the Move drop effect when the user drags the payload over button1. It also checks if the payload is present and is an array of integers.

private void button1_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(int[])))
        e.Effect = DragDropEffects.Move;
    else
        e.Effect = DragDropEffects.None;
}

The last step is to receive the dropped data. You can do that by handling the DragDrop event. it is fired when the user finally releases the pointer over the target control.

private void button1_DragDrop(object sender, DragEventArgs e)
{
    var indexes = (int[])e.Data.GetData(typeof(int[]));
}

Data Object

The data object exposed by the DragEventArgs event data can hold any type of data and provides all sorts of functionality to check the presence of the data and extract the data.

Drag & drop data is not limited to one format; you can create a DataObject, assign multiple data with different formats and use it in the call to DoDragDrop().

Detect Target

When the target is not a simple control like a button or a field, but it may contain multiple inner parts, you may need to detect where exactly the payload was dropped. In a ListBox you want to detect the item that received the drop, in a TreeView the child node, or in a DataGridView the specific row.

You will find the exact target in the e.DropTarget property. This is different for each control.

ControlDropTarget

ListBox

Item

TreeView

TreeNode

DataGridView

DataGridViewCell

ListView

ListViewItem

In addition to the DropTarget property, the event data contains the location of the pointer and the key state of the keyboard to allow your app to detect what the user is pressing while dragging, in case you want to handle different drag effects.

Drag Icon

When dragging, Wisej shows the typical drag cursor you see in a desktop application (themeable).

However, you can change the drag cursor at any time and use any image of any size simply by assigning the e.Image, or e.ImageSource and e.ImageSize properties in any of the drag & drop events.

Dropping Files

Another super cool feature in Wisej (and only in Wisej ) is the ability to drag & drop any file(s) from your desktop onto any control.

You can check the files being dropped in the DragEnter event by retrieving the list of mime types (nothing else is available in the browser) being dropped from the data object using DataFormats.FileDrop like this:

private void label1_DragEnter(object sender, DragEventArgs e)
{
	var fileTypes = (string[])e.Data.GetData(DataFormats.FileDrop);
	if (fileTypes.Length > 0 && fileTypes[0]=="image/png")
		e.Effect = DragDropEffects.Move;
}

And finally retrieve the files being dropped simply by handling the DragDrop event and using DataFormats.Files to receive an instance of the HttpFileCollection class:

private void label1_DragDrop(object sender, DragEventArgs e)
{
	var data = (System.Web.HttpFileCollection)e.Data.GetData(DataFormats.Files);
	if (data.Count == 1)
	{
		this.label1.Text = "";
		this.label1.Image = Image.FromStream(data[0].InputStream);
	}
}

It's that simple.

To enable dragging and dropping entire folders, enable the "allow.drop.folders" option in Default.json: options:{"allow.drop.folders": true}.

Last updated