Edit this page

Combining RadDragDropService and OLE drag-and-drop

This article demonstrates a sample approach how to achieve drag and drop functionality between RadListView and RadListControl. For this purpose, we will use a combination between the RadDragDropService, supported by the RadListView control, and the OLE drag-and-drop, which is supported by all controls from the Telerik UI for WinForms suite.

Let’s assume that our RadListView is in bound mode and its ViewType property is set to IconsView. The RadListControl is populated manually with items. Set the AllowDrop property to true for both of the controls. Additionally, you need to set the RadListView.AllowDragDrop property to true as well.

Populating with data


BindingList<string> items = new BindingList<string>();
for (int i = 0; i < 10; i++)
{
    items.Add("Item" + i);                
    this.radListControl1.Items.Add("ListControlItem" + i);
}

this.radListView1.DataSource = items;
this.radListView1.AllowDragDrop = true;
this.radListView1.AllowDrop = true;
this.radListControl1.AllowDrop = true;
this.radListView1.ViewType = Telerik.WinControls.UI.ListViewType.IconsView;

Dim items As New BindingList(Of String)()
For i As Integer = 0 To 9
    items.Add("Item" & i)
    Me.RadListControl1.Items.Add("ListControlItem" & i)
Next
Me.RadListView1.DataSource = items
Me.RadListView1.AllowDragDrop = True
Me.RadListView1.AllowDrop = True
Me.RadListControl1.AllowDrop = True
Me.RadListView1.ViewType = Telerik.WinControls.UI.ListViewType.IconsView

Drag and drop from RadListView to RadListControl using RadDragDropService

Figure 1: Drag and drop from RadListView to RadListControl using RadDragDropService

listview-drag-and-drop-combining-raddragdropservice-and-ole-drag-and-drop 001

To implement drag and drop functionality for this scenario, we will use the ListViewElement.DragDropService, which is a derivative of the In the PreviewDragOver event allow dropping over a RadListElement. The PreviewDragDrop event performs the actual inserting of the dragged item into the RadListControl.Items collection:

Handling the RadDragDropService's events


private void DragDropService_PreviewDragOver(object sender, Telerik.WinControls.RadDragOverEventArgs e)
{
    e.CanDrop = e.HitTarget is RadListElement;
}

private void DragDropService_PreviewDragDrop(object sender, Telerik.WinControls.RadDropEventArgs e)
{ 
    BaseListViewVisualItem draggedItem = e.DragInstance as BaseListViewVisualItem;
    RadListElement listElement = e.HitTarget as RadListElement;

    if (listElement == null)
    {
        return;
    }
    e.Handled = true;         
    RadListControl listControl = listElement.ElementTree.Control as RadListControl;
    RadListVisualItem targetItem = listControl.ElementTree.GetElementAtPoint(e.DropLocation) as RadListVisualItem;
    int indexToInsert;
    if (targetItem != null)
    {
        indexToInsert = targetItem.Data.RowIndex;
    }
    else
    {
        indexToInsert = listControl.Items.Count;
    }
    RadListDataItem newItem = new RadListDataItem(draggedItem.Data.Text);
    listControl.Items.Insert(indexToInsert, newItem);

    draggedItem.Data.ListView.Items.Remove(draggedItem.Data);
}

Private Sub DragDropService_PreviewDragOver(sender As Object, e As Telerik.WinControls.RadDragOverEventArgs)
    e.CanDrop = TypeOf e.HitTarget Is RadListElement
End Sub
Private Sub DragDropService_PreviewDragDrop(sender As Object, e As Telerik.WinControls.RadDropEventArgs)
    Dim draggedItem As BaseListViewVisualItem = TryCast(e.DragInstance, BaseListViewVisualItem)
    Dim listElement As RadListElement = TryCast(e.HitTarget, RadListElement)
    If listElement Is Nothing Then
        Return
    End If
    e.Handled = True
    Dim listControl As RadListControl = TryCast(listElement.ElementTree.Control, RadListControl)
    Dim targetItem As RadListVisualItem = TryCast(listControl.ElementTree.GetElementAtPoint(e.DropLocation), RadListVisualItem)
    Dim indexToInsert As Integer
    If targetItem IsNot Nothing Then
        indexToInsert = targetItem.Data.RowIndex
    Else
        indexToInsert = listControl.Items.Count
    End If
    Dim newItem As New RadListDataItem(draggedItem.Data.Text)
    listControl.Items.Insert(indexToInsert, newItem)
    draggedItem.Data.ListView.Items.Remove(draggedItem.Data)
End Sub

Drag and drop from RadListControl to RadListView using the OLE drag-and-drop

Figure 2: Drag and drop from RadListControl to RadListView using the OLE drag-and-drop

listview-drag-and-drop-combining-raddragdropservice-and-ole-drag-and-drop 002

1. Firstly, we should start the drag and drop operation using the RadListControl.MouseMove event when the left mouse button is pressed. We should keep the mouse down location in the RadListControl.MouseDown event. Afterwards, allow dragging over the RadListView via the Effect argument of the DragEventArgs in the RadListView.DragEnter event handler:

Starting the drag and drop operation


private Point mouseDownPosition;
private bool isDragging;
private void radListControl1_MouseDown(object sender, MouseEventArgs e)
{
    this.mouseDownPosition = e.Location;
}
private void radListControl1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button != MouseButtons.Left)
    {
        this.isDragging = false;
        return;
    }
    if (this.isDragging)
    {
        return;
    }
    if (this.ShouldBeginDrag(this.mouseDownPosition, e.Location))
    {
        RadListVisualItem draggedItem = this.radListControl1.ElementTree.GetElementAtPoint(this.mouseDownPosition) as RadListVisualItem;
        if (draggedItem != null)
        {
            this.isDragging = true;
            //start the drag and drop operation
            (sender as RadListControl).DoDragDrop(draggedItem.Data, DragDropEffects.Copy);
        }
    }
}

private bool ShouldBeginDrag(Point current, Point capture)
{
    Size dragSize = SystemInformation.DragSize;
    Rectangle dragRect = new Rectangle(capture.X - dragSize.Width / 2,
        capture.Y - dragSize.Height / 2, dragSize.Width, dragSize.Height);
    return !dragRect.Contains(current);
}

private void radListView1_DragEnter(object sender, DragEventArgs e)
{
    e.Effect = DragDropEffects.Copy;
}

Private mouseDownPosition As Point
Private isDragging As Boolean
Private Sub radListControl1_MouseDown(sender As Object, e As MouseEventArgs)
    Me.mouseDownPosition = e.Location
End Sub
Private Sub radListControl1_MouseMove(sender As Object, e As MouseEventArgs)
    If e.Button <> MouseButtons.Left Then
        Me.isDragging = False
        Return
    End If
    If Me.isDragging Then
        Return
    End If
    If Me.ShouldBeginDrag(Me.mouseDownPosition, e.Location) Then
        Dim draggedItem As RadListVisualItem = TryCast(Me.RadListControl1.ElementTree.GetElementAtPoint(Me.mouseDownPosition), RadListVisualItem)
        If draggedItem IsNot Nothing Then
            Me.isDragging = True
            'start the drag and drop operation
            TryCast(sender, RadListControl).DoDragDrop(draggedItem.Data, DragDropEffects.Copy)
        End If
    End If
End Sub
Private Function ShouldBeginDrag(current As Point, capture As Point) As Boolean
    Dim dragSize As Size = SystemInformation.DragSize
    Dim dragRect As New Rectangle(capture.X - dragSize.Width / 2, capture.Y - dragSize.Height / 2, dragSize.Width, dragSize.Height)
    Return Not dragRect.Contains(current)
End Function
Private Sub radListView1_DragEnter(sender As Object, e As DragEventArgs)
    e.Effect = DragDropEffects.Copy
End Sub

2. In the RadListView.DragDrop event you need to get the location of the mouse and convert it to a point that the RadListView can use to get the element underneath the mouse. Afterwards, insert the dragged item on the specific position. We should reset the stored mouse down location as well:

Handle the drop operation


private void radListView1_DragDrop(object sender, DragEventArgs e)
{
    RadListView listView = sender as RadListView;
    Point point = listView.PointToClient(new Point(e.X, e.Y));
    BaseListViewVisualItem targetItem = listView.ElementTree.GetElementAtPoint(point) as BaseListViewVisualItem;
    RadListDataItem draggedItem = e.Data.GetData(typeof(RadListDataItem)) as RadListDataItem;

    BindingList<string> targetDataSource = listView.DataSource as BindingList<string>; 
    if (targetDataSource != null)
    {
        //you are dropping over an item
        if (targetItem != null)
        {
            int targetIndex = listView.Items.IndexOf(targetItem.Data);

            targetDataSource.Insert(targetIndex, draggedItem.Text);
        }
        else // you are dropping over the ListViewElement
        {
            targetDataSource.Add(draggedItem.Text);
        }
    }

    int indexToRemove = this.radListControl1.Items.IndexOf(draggedItem);
    if (indexToRemove > -1)
    {
        this.radListControl1.Items.RemoveAt(indexToRemove);
    }
    this.mouseDownPosition = Point.Empty;
    this.isDragging = false;
}

private void radListControl1_MouseUp(object sender, MouseEventArgs e)
{
    this.mouseDownPosition = Point.Empty;
    this.isDragging = false;
}

Private Sub radListView1_DragDrop(sender As Object, e As DragEventArgs)
    Dim listView As RadListView = TryCast(sender, RadListView)
    Dim point__1 As Point = listView.PointToClient(New Point(e.X, e.Y))
    Dim targetItem As BaseListViewVisualItem = TryCast(listView.ElementTree.GetElementAtPoint(point__1), BaseListViewVisualItem)
    Dim draggedItem As RadListDataItem = TryCast(e.Data.GetData(GetType(RadListDataItem)), RadListDataItem)
    Dim targetDataSource As BindingList(Of String) = TryCast(listView.DataSource, BindingList(Of String))
    If targetDataSource IsNot Nothing Then
        'you are dropping over an item
        If targetItem IsNot Nothing Then
            Dim targetIndex As Integer = listView.Items.IndexOf(targetItem.Data)
            targetDataSource.Insert(targetIndex, draggedItem.Text)
        Else
            ' you are dropping over the ListViewElement
            targetDataSource.Add(draggedItem.Text)
        End If
    End If
    Dim indexToRemove As Integer = Me.RadListControl1.Items.IndexOf(draggedItem)
    If indexToRemove > -1 Then
        Me.RadListControl1.Items.RemoveAt(indexToRemove)
    End If
    Me.mouseDownPosition = Point.Empty
    Me.isDragging = False
End Sub
Private Sub radListControl1_MouseUp(sender As Object, e As MouseEventArgs)
    Me.mouseDownPosition = Point.Empty
    Me.isDragging = False
End Sub

See Also