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";
}

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


this.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 ;
    }
}

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);
            }
        }
    }
}