ListBox DragDropBehavior

The ListBoxDragDropBehavior class enables customizeable drag/drop functionality in RadListBox and the Silverlight native ListBox.

This article shows how to use the behavior in the ListBox control. For RadListBox, see its Drag and Drop documentation.

To use the behavior with ListBox, set the ListBoxDragDrop.Behavior attached property. Additional to this, the DragDropManager.AllowDrag or DragDropManager.AllowCapturedDrag attached property should be set to the ListBoxItems elements. This can be done via the ItemContainerStyle property of the control.

Setting up the ListBox and the drag/drop behavior

<ListBox ItemsSource="{Binding MyItemsCollection}" DisplayMemberPath="Name"> 
    <ListBox.ItemContainerStyle> 
        <Style TargetType="ListBoxItem">  
            <Setter Property="telerik:DragDropManager.AllowCapturedDrag" Value="True" />  
        </Style>  
    </ListBox.ItemContainerStyle> 
    <telerik:ListBoxDragDrop.Behavior> 
        <telerik:ListBoxDragDropBehavior /> 
    </telerik:ListBoxDragDrop.Behavior> 
</ListBox> 

The default drag/drop behavior is to reorder the items if the drag/drop happens in the same ListBox instance. Dropping an item to another ListBox instance will remove it from the source control and add it to the target. If you hold the Ctrl key while dropping an item in another ListBox, the item will get copied.

Copy Item in the Same ListBox

By default, dragging with the Ctrl key pressed makes a copy of the dragged item on drop. This doesn't happen if the item is dropped in the same ListBox instance. To allow this behavior, create a class that derives from ListBoxDragDropBehavior and override its CopyDraggedItems method.

Creating custom drag drop behavior that allows copy items in the same ListBox instance

public class CustomListBoxDragDropBehavior : ListBoxDragDropBehavior 
{ 
    protected override IEnumerable<object> CopyDraggedItems(DragDropState state) 
    { 
        var copiedItems = new List<object>(); 
        foreach (object item in state.DraggedItems) 
        { 
            object copy = CreateItemCopy(item); 
            copiedItems.Add(copy); 
        } 
        return copiedItems; 
    } 
 
    private object CreateItemCopy(object originaItem) 
    { 
        // create and return a copy of the item 
    } 
} 

Using the custom behavior

<ListBox>        
    <telerik:ListBoxDragDrop.Behavior> 
        <local:CustomListBoxDragDropBehavior /> 
    </telerik:ListBoxDragDrop.Behavior> 
</ListBox> 

Disable Item Reorder

The default drag/drop behavior within the same ListBox instance is to reorder the items. To disable this, set the AllowReorder property of ListBoxDragDropBehavior to false.

Disabling reordering

<telerik:ListBoxDragDropBehavior AllowReorder="False" /> 

Setting Item Type

The ListBoxDragDropBehavior automatically recognizes the item Type based on the ItemsSource of its host control and then automatically adds the dragged items that are of this type. In some cases the behavior my not recognize the item type correctly. In that situation, use the ItemType property of the ListBoxDragDropBehavior in order to manually assign the type.

Setting the ItemType

<drag:ListBoxDragDropBehavior ItemType="{x:Type local:MyItemClass}" /> 

Customizing the Drag and Drop Operation

The ListBoxDragDropBehavior class derives from the DragDropBehavior, which provides several methods that can be overridden in order to modify the actions that happen on drag and drop. Read more about the available methods in the DragDropBehavior article.

Converting Data

In scenarios with drag/drop between controls containing different item types the drag data should be converted using a DataConverter. The following example shows how to implement a converter and assign it to the host control. The converter example uses sample class names (Appointment and Customer) that can vary on your exact implementation and naming.

Creating the DataConverter class

public class CustomerToAppointmentConverter : DataConverter 
{ 
    public override string[] GetConvertToFormats() 
    { 
        return new string[] { typeof(Appointment).FullName, typeof(Customer).FullName }; 
    } 
 
    public override object ConvertTo(object data, string format) 
    { 
        var customers = (IEnumerable)DataObjectHelper.GetData(data, typeof(Customer), false); 
        if (customers != null && format == typeof(Appointment).FullName) 
        { 
            return customers.OfType<Customer>().Select(c => new Appointment { Subject = c.Name }); 
        } 
        var appointments = (IEnumerable)DataObjectHelper.GetData(data, typeof(Appointment), false); 
        if (appointments != null && format == typeof(Customer).FullName) 
        { 
            return appointments.OfType<Appointment>().Select(a => new Customer { Name = a.Subject });    
        } 
        return null; 
    }    
} 

Using the custom DataConverter

<ListBox> 
    <telerik:ListBoxDragDrop.DataConverter> 
        <local:CustomerToAppointmentConverter /> 
    </telerik:ListBoxDragDrop.DataConverter> 
    <telerik:ListBoxDragDrop.Behavior> 
        <telerik:ListBoxDragDropBehavior /> 
    </telerik:ListBoxDragDrop.Behavior> 
</ListBox> 
In this article