In this post I will demonstrate how to extend the Drag Drop functionality of the RadDragAndDropManager adding command support by using the attached behaviors extensibility. That way one can easily move the logic for the operation from the code behind into your model and work only with the Data object. To demonstrate the idea I will use scenario where items are being dragged between ListBoxes.
The behavior transforms the Drag Drop events into commands. It exposes the following properties:
- DragCommand – executed when dragInfo event is raised.
- DropCommand – executed when dropInfo event is raised.
- DragCueTemplate – data template that defines the dragcue appearance.
The command parameter being transferred to the commands contains the data describing the drag status. In order to handle more specific cases we can transmit additional information to the viewmodel by adding additional properties:
public class DragDropParameter
{
public object DraggedItem { get; set; }
public IEnumerable ItemsSource { get; set; }
public DragStatus DragStatus { get; set; }
}
What we need to do in our viewmodel is the following:
public DelegateCommand<DragDropParameter> DragCommand { get; private set; }
public DelegateCommand<DragDropParameter> DropCommand { get; private set; }
public MainViewModel()
{
this.DragCommand = new DelegateCommand<DragDropParameter>(
(c) =>
{
if (c.DragStatus == DragStatus.DragComplete)
{
((IList)c.ItemsSource).Remove(c.DraggedItem);
}
},
(c) =>
{
return true;
}
);
this.DropCommand = new DelegateCommand<DragDropParameter>(
(c) =>
{
if (c.DragStatus == DragStatus.DropComplete)
{
((IList)c.ItemsSource).Add(c.DraggedItem);
}
},
(c) =>
{
return true;
}
);
}
And finally defining our drag cue and attaching the behavior in XAML:
<Grid.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="telerik:RadDragAndDropManager.AllowDrag" Value="True"></Setter>
<Setter Property="telerik:RadDragAndDropManager.AllowDrop" Value="True"></Setter>
</Style>
<Style TargetType="ListBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding UserName}"></TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="DragCueTemplate">
<StackPanel Background="LightGreen">
<TextBlock Margin="5" Text="Dragging :"></TextBlock>
<TextBlock Margin="5" FontWeight="Bold" Text="{Binding UserName}"></TextBlock>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<ListBox x:Name="sourceGrid" ItemsSource="{Binding SourceData}">
<i:Interaction.Behaviors>
<local:CommandDragDropBehavior DragCommand="{Binding DragCommand}" DropCommand="{Binding DropCommand}" DragCueTemplate="{StaticResource DragCueTemplate}"></local:CommandDragDropBehavior>
</i:Interaction.Behaviors>
</ListBox>
<ListBox x:Name="destinationGrid" Grid.Column="1" ItemsSource="{Binding DestinationData}">
<i:Interaction.Behaviors>
<local:CommandDragDropBehavior DragCommand="{Binding DragCommand}" DropCommand="{Binding DropCommand}" DragCueTemplate="{StaticResource DragCueTemplate}"></local:CommandDragDropBehavior>
</i:Interaction.Behaviors>
</ListBox>
If you like this functionality you can check the attached project demonstrating this in action
Download Source SL4
Download Source WPF