New to Telerik UI for WinForms? Download free 30-day trial

Drag and Drop in bound mode

When RadListView is in bound mode, it does not support drag and drop functionality out of the box due to the specificity of the data source. However, this can be easily achieved by using the built-in ListViewDragDropService. You only need to handle events, emanating from this service.

Figure 1: Drag and drop in bound mode

WinForms RadListView Drag and drop in bound mode

1. Let’s start with populating the RadListView with data. For this purpose we will create a class Item and fill a BindingList with items:


public class Item
{
    public string UniqueId { get; set; }

    public string Title { get; set; }

    public bool IsActive { get; set; }

    public DateTime CreatedOn { get; set; }

    public Item(string uniqueId, string title, bool isActive, DateTime createdOn)
    {
        this.UniqueId = uniqueId;
        this.Title = title;
        this.IsActive = isActive;
        this.CreatedOn = createdOn;
    }
}

public DragDropInBoundMode()
{
    InitializeComponent();

    BindingList<Item> items = new BindingList<Item>();
    for (int i = 0; i < 30; i++)
    {
        items.Add(new Item(Guid.NewGuid().ToString(),
            "Item" + i,i % 2 == 0,DateTime.Now.AddDays(i)));
    }

    this.radListView1.DataSource = items;
    this.radListView1.DisplayMember = "Title";
}

Public Class Item
    Public Property UniqueId() As String
        Get
            Return m_UniqueId
        End Get
        Set(value As String)
            m_UniqueId = value
        End Set
    End Property
    Private m_UniqueId As String
    Public Property Title() As String
        Get
            Return m_Title
        End Get
        Set(value As String)
            m_Title = value
        End Set
    End Property
    Private m_Title As String
    Public Property IsActive() As Boolean
        Get
            Return m_IsActive
        End Get
        Set(value As Boolean)
            m_IsActive = value
        End Set
    End Property
    Private m_IsActive As Boolean
    Public Property CreatedOn() As DateTime
        Get
            Return m_CreatedOn
        End Get
        Set(value As DateTime)
            m_CreatedOn = value
        End Set
    End Property
    Private m_CreatedOn As DateTime
    Public Sub New(uniqueId As String, title As String, isActive As Boolean, createdOn As DateTime)
        Me.UniqueId = uniqueId
        Me.Title = title
        Me.IsActive = isActive
        Me.CreatedOn = createdOn
    End Sub
End Class
Public Sub New()
    InitializeComponent()
    Dim items As New BindingList(Of Item)()
    For i As Integer = 0 To 9
        items.Add(New Item(Guid.NewGuid().ToString(), "Item" & i, i Mod 2 = 0, DateTime.Now.AddDays(i)))
    Next
    Me.RadListView1.DataSource = items
    Me.RadListView1.DisplayMember = "Title"
End Sub

2. In order to enable the drag and drop functionality, set the RadListView.AllowDragDrop property to true:


this.radListView1.AllowDragDrop = true;

Me.RadListView1.AllowDragDrop = True

3. Use the ListViewElement.DragDropService.PreviewDragStart event to get the dragged item. Subscribe to the ListViewElement.DragDropService.PreviewDragOver event, which allows you to control on what targets the item, being dragged, can be dropped on:


Item sourceBoundItem;

private void DragDropService_PreviewDragStart(object sender, PreviewDragStartEventArgs e)
{
    SimpleListViewVisualItem sourceItem = e.DragInstance as SimpleListViewVisualItem;
    if (sourceItem != null)
    {
        sourceBoundItem = sourceItem.Data.DataBoundItem as Item;
    }
}

private void DragDropService_PreviewDragOver(object sender, RadDragOverEventArgs e)
{
    if (e.DragInstance is SimpleListViewVisualItem)
    {
        e.CanDrop = e.HitTarget is SimpleListViewVisualItem ||
                    e.HitTarget is SimpleListViewElement ;
    }
}

Private sourceBoundItem As Item
Private Sub DragDropService_PreviewDragStart(sender As Object, e As PreviewDragStartEventArgs)
    Dim sourceItem As SimpleListViewVisualItem = TryCast(e.DragInstance, SimpleListViewVisualItem)
    If sourceItem IsNot Nothing Then
        sourceBoundItem = TryCast(sourceItem.Data.DataBoundItem, Item)
    End If
End Sub
Private Sub DragDropService_PreviewDragOver(sender As Object, e As RadDragOverEventArgs)
    If TypeOf e.DragInstance Is SimpleListViewVisualItem Then
        e.CanDrop = TypeOf e.HitTarget Is SimpleListViewVisualItem OrElse TypeOf e.HitTarget Is SimpleListViewElement
    End If
End Sub

4. The last event we need to handle in our implementation is the ListViewElement.DragDropService.PreviewDragDrop event. This is where we will initiate the actual physical move of the item from one position to another. Implement the handler as follows:


private void DragDropService_PreviewDragDrop(object sender, RadDropEventArgs e)
{
    e.Handled = true;

    SimpleListViewVisualItem targetItem = e.HitTarget as SimpleListViewVisualItem;
    SimpleListViewVisualItem sourceItem = e.DragInstance as SimpleListViewVisualItem;
    SimpleListViewElement viewElement = e.HitTarget as SimpleListViewElement; 
    if ((targetItem == null || sourceItem == null) && viewElement == null)
    {
        return;
    }
    BindingList<Item> dataSource = sourceItem.Data.ListView.DataSource as BindingList<Item> ;
    if (dataSource != null)
    {
        if (sourceBoundItem != null)
        {
            int sourceIndex = dataSource.IndexOf(sourceBoundItem);
            if (viewElement != null)
            {
                //add the dragged item at last position
                dataSource.RemoveAt(sourceIndex);
                dataSource.Add(sourceBoundItem);
            }
            else
            {
                viewElement = sourceItem.Data.ListView.ListViewElement.ViewElement as SimpleListViewElement;
                //reorder the items in the BindingList
                Item targetBoundItem = targetItem.Data.DataBoundItem as Item;

                dataSource.RemoveAt(sourceIndex);  
                int targetIndex = dataSource.IndexOf(targetBoundItem);

                if (viewElement.ShouldDropAfter(targetItem, e.DropLocation))
                {
                    targetIndex++;
                }
                dataSource.Insert(targetIndex, sourceBoundItem);
            }
        }
    }
}

Private Sub DragDropService_PreviewDragDrop(sender As Object, e As RadDropEventArgs)
    e.Handled = True
    Dim targetItem As SimpleListViewVisualItem = TryCast(e.HitTarget, SimpleListViewVisualItem)
    Dim sourceItem As SimpleListViewVisualItem = TryCast(e.DragInstance, SimpleListViewVisualItem)
    Dim viewElement As SimpleListViewElement = TryCast(e.HitTarget, SimpleListViewElement)
    If (targetItem Is Nothing OrElse sourceItem Is Nothing) AndAlso viewElement Is Nothing Then
        Return
    End If
    Dim dataSource As BindingList(Of Item) = TryCast(sourceItem.Data.ListView.DataSource, BindingList(Of Item))
    If dataSource IsNot Nothing Then
        If sourceBoundItem IsNot Nothing Then
            Dim sourceIndex As Integer = dataSource.IndexOf(sourceBoundItem)
            If viewElement IsNot Nothing Then
                'add the dragged item at last position
                dataSource.RemoveAt(sourceIndex)
                dataSource.Add(sourceBoundItem)
            Else
                viewElement = TryCast(sourceItem.Data.ListView.ListViewElement.ViewElement, SimpleListViewElement)
                'reorder the items in the BindingList
                Dim targetBoundItem As Item = TryCast(targetItem.Data.DataBoundItem, Item)
                dataSource.RemoveAt(sourceIndex)
                Dim targetIndex As Integer = dataSource.IndexOf(targetBoundItem)
                If viewElement.ShouldDropAfter(targetItem, e.DropLocation) Then
                    targetIndex += 1
                End If
                dataSource.Insert(targetIndex, sourceBoundItem)
            End If
        End If
    End If
End Sub

See Also

In this article