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

Drag and Drop using RadDragDropService

This article will guide you through the process of achieving drag and drop functionality from RadListView to RadGridView and vice versa. For this purpose, we will use the RadDragDropService, supported by both of the controls. Let’s assume that the RadListView is in unbound mode and the ViewType property is set to DetailsView. The RadGridView is bound to a DataTable with identical columns as the manually added ones to the RadListView.

Populating with data


DataTable gridViewDataTable = new DataTable();

public DragDropRadDragDropService()
{
    InitializeComponent();

    this.radListView1.Columns.Add("Id");
    this.radListView1.Columns.Add("Title");
    this.radListView1.ViewType = Telerik.WinControls.UI.ListViewType.DetailsView;

    List<string> products = new List<string>()
    {
        "Telerik UI for WinForms",
        "Telerik UI for Silverlight",
        "Telerik UI for WPF",
        "Telerik UI for ASP.NET AJAX"
    };
    for (int i = 0; i < products.Count; i++)
    {
        ListViewDataItem item = new ListViewDataItem();
        this.radListView1.Items.Add(item);
        item["Id"] = Guid.NewGuid().ToString();
        item["Title"] = products[i];
    }

    gridViewDataTable.Columns.Add("Id", typeof(string));
    gridViewDataTable.Columns.Add("Title", typeof(string));
    gridViewDataTable.Rows.Add(Guid.NewGuid().ToString(), "Kendo UI");
    gridViewDataTable.Rows.Add(Guid.NewGuid().ToString(), "Telerik UI for iOS");
    gridViewDataTable.Rows.Add(Guid.NewGuid().ToString(), "Telerik UI for Android");
    gridViewDataTable.Rows.Add(Guid.NewGuid().ToString(), "Telerik UI for Windows Phone");
    this.radGridView1.DataSource = gridViewDataTable;
}

Drag and Drop from RadGridView to RadListView

Figure 1: Drag and Drop from RadGridView to RadListView

WinForms RadListView Drag and Drop from RadGridView to RadListView

1. The first thing we need to do is to start the RadGridView’s drag and drop service when a user clicks on a row with the left mouse down. For this purpose, we should create a custom grid behavior:

Starting a drag and drop operation


//initiates drag and drop service for clicked rows
public class CustomRowGridBehavior : GridDataRowBehavior
{
    protected override bool OnMouseDownLeft(MouseEventArgs e)
    {
        GridDataRowElement row = this.GetRowAtPoint(e.Location) as GridDataRowElement;
        if (row != null)
        {
            RadGridViewDragDropService svc = this.GridViewElement.GetService<RadGridViewDragDropService>();
            svc.Start(row);
        }
        return base.OnMouseDownLeft(e);
    }
}

2. Next, we should register this behavior in our grid:

Register the custom row behavior


//register the custom row behavior
BaseGridBehavior gridBehavior = this.radGridView1.GridBehavior as BaseGridBehavior;
gridBehavior.UnregisterBehavior(typeof(GridViewDataRowInfo));
gridBehavior.RegisterBehavior(typeof(GridViewDataRowInfo), new CustomRowGridBehavior());

3. It is necessary to subscribe to the PreviewDragStart, PreviewDragOver and PreviewDragDrop events of the grid’s RadDragDropService. The PreviewDragStart event is fired once the drag and drop service on the grid is started. We should notify the service that the drag and drop operation can move forward. In the PreviewDragOver event you can control on what targets to allow dropping the dragged row. The PreviewDragDrop event performs the actual move of the row from the RadGridView to the RadListView.

Handling the RadDragDropService's events


private void svc_PreviewDragStart(object sender, PreviewDragStartEventArgs e)
{
    e.CanStart = true;
}

private void svc_PreviewDragOver(object sender, RadDragOverEventArgs e)
{
    if (e.DragInstance is GridDataRowElement)
    {
        e.CanDrop = e.HitTarget is DetailListViewDataCellElement ||
                    e.HitTarget is DetailListViewElement;
    }
}

private void svc_PreviewDragDrop(object sender, RadDropEventArgs e)
{
    DetailListViewDataCellElement targetCell = e.HitTarget as DetailListViewDataCellElement;
    DetailListViewElement targetElement = e.HitTarget as DetailListViewElement;
    GridDataRowElement draggedRow = e.DragInstance as GridDataRowElement;

    if (draggedRow == null)
    {
        return;
    }
    ListViewDataItem item = new ListViewDataItem();            
    DataRow draggedDataBoundItem = ((DataRowView)draggedRow.RowInfo.DataBoundItem).Row;
    if (targetElement != null)
    {
        ((RadListViewElement)targetElement.Parent).Items.Add(item) ;
    }
    if (targetCell != null)
    {
        BaseListViewVisualItem targetVisualItem = targetCell.RowElement;

        int insertIndex = targetCell.Row.ListView.Items.IndexOf(targetVisualItem.Data);
        if (insertIndex > -1)
        {
            targetCell.Row.ListView.Items.Insert(insertIndex, item);
        }
    }
    item["Id"] = draggedDataBoundItem["Id"];
    item["Title"] = draggedDataBoundItem["Title"];

    gridViewDataTable.Rows.Remove(draggedDataBoundItem);
}

Drag and Drop from RadListView to RadGridView

Figure 2: Drag and Drop from RadListView to RadGridView

WinForms RadListView Drag and Drop from RadListView to RadGridView

1. In order to enable dragging an item from the RadListView and dropping it onto the RadGridView, it is necessary to set the RadListView.AllowDragDrop property to true.

Subscribing to the RadDragDropService's events


this.radListView1.ListViewElement.DragDropService.PreviewDragOver += DragDropService_PreviewDragOver;
this.radListView1.ListViewElement.DragDropService.PreviewDragDrop += DragDropService_PreviewDragDrop;

2. To implement drag and drop functionality for this scenario, we will use the ListViewElement.DragDropService, which is a derivative of the RadDragDropService . Subscribe to its PreviewDragOver and PreviewDragDrop events. In the PreviewDragOver event allow dropping over a row element or over the table element. The PreviewDragDrop event performs the actual inserting of the dragged item into the RadGridView’s data source:

Handling the RadDragDropService's events


private void DragDropService_PreviewDragOver(object sender, RadDragOverEventArgs e)
{
    e.CanDrop = e.HitTarget is GridTableElement ||
                e.HitTarget is GridDataRowElement;
}

private void DragDropService_PreviewDragDrop(object sender, RadDropEventArgs e)
{
    BaseListViewVisualItem draggedItem = e.DragInstance as BaseListViewVisualItem;
    GridDataRowElement rowElement = e.HitTarget as GridDataRowElement;
    GridTableElement tableElement = e.HitTarget as GridTableElement;

    if (rowElement == null && tableElement == null)
    {
        return;
    }
    e.Handled = true;           
    DataRow newRow = gridViewDataTable.NewRow();
    if (tableElement != null)
    {
        gridViewDataTable.Rows.Add(newRow);
    }
    if (rowElement != null)
    {
        GridViewRowInfo targetRow = rowElement.RowInfo;

        int insertIndex = this.radGridView1.Rows.IndexOf(targetRow);
        if (insertIndex > -1)
        {
            gridViewDataTable.Rows.InsertAt(newRow, insertIndex);
        }
    }
    newRow["Id"] = draggedItem.Data["Id"];
    newRow["Title"] = draggedItem.Data["Title"];

    this.radListView1.Items.Remove(draggedItem.Data);
}