Getting Started with WPF DragDropManager
This article will demonstrate a basic implementation of the DragDropManager by dragging between two ListBoxes.
In order to use DragDropManager you have to add reference to Telerik.Windows.Controls assembly.
To learn how to use the DragDropManager in a more MVVM-friendly matter though commands, have a look at the "DragDrop Using Commands" demo from our SDK Samples Browser. The source code of the demo is also available in our GitHub repository.
Firstly, for the purpose of this tutorial we will create a business object ApplicationInfo, which will expose a couple of properties as well as a sample collection for populating the ListBoxes. The structure of the class used in this example is shown on the next code snippets:
Example 1: Create ApplicationInfo
public class ApplicationInfo
{
public Double Price
{
get;
set;
}
public String IconPath
{
get;
set;
}
public String Name
{
get;
set;
}
public String Author
{
get;
set;
}
public static ObservableCollection<ApplicationInfo> GenerateApplicationInfos()
{
ObservableCollection<ApplicationInfo> result = new ObservableCollection<ApplicationInfo>();
ApplicationInfo info1 = new ApplicationInfo();
info1.Name = "Large Collider";
info1.Author = "C.E.R.N.";
info1.IconPath = @"img/Atom.png";
result.Add(info1);
ApplicationInfo info2 = new ApplicationInfo();
info2.Name = "Paintbrush";
info2.Author = "Imagine Inc.";
info2.IconPath = @"img/Brush.png";
result.Add(info2);
ApplicationInfo info3 = new ApplicationInfo();
info3.Name = "Lively Calendar";
info3.Author = "Control AG";
info3.IconPath = @"img/CalendarEvents.png";
result.Add(info3);
ApplicationInfo info4 = new ApplicationInfo();
info4.Name = "Fire Burning ROM";
info4.Author = "The CD Factory";
info4.IconPath = @"img/CDBurn.png";
result.Add(info4);
ApplicationInfo info5 = new ApplicationInfo();
info5.Name = "Fav Explorer";
info5.Author = "Star Factory";
info5.IconPath = @"img/favorites.png";
result.Add(info5);
ApplicationInfo info6 = new ApplicationInfo();
info6.Name = "IE Fox";
info6.Author = "Open Org";
info6.IconPath = @"img/Connected.png";
result.Add(info6);
ApplicationInfo info7 = new ApplicationInfo();
info7.Name = "Charting";
info7.Author = "AA-AZ inc";
info7.IconPath = @"img/ChartDot.png";
result.Add(info7);
ApplicationInfo info8 = new ApplicationInfo();
info8.Name = "SuperPlay";
info8.Author = "EB Games";
info8.IconPath = @"img/Games.png";
result.Add(info8);
return result;
}
}
Public Class ApplicationInfo
Public Property Price() As [Double]
Get
Return m_Price
End Get
Set
m_Price = Value
End Set
End Property
Private m_Price As [Double]
Public Property IconPath() As [String]
Get
Return m_IconPath
End Get
Set
m_IconPath = Value
End Set
End Property
Private m_IconPath As [String]
Public Property Name() As [String]
Get
Return m_Name
End Get
Set
m_Name = Value
End Set
End Property
Private m_Name As [String]
Public Property Author() As [String]
Get
Return m_Author
End Get
Set
m_Author = Value
End Set
End Property
Private m_Author As [String]
Public Shared Function GenerateApplicationInfos() As ObservableCollection(Of ApplicationInfo)
Dim result As New ObservableCollection(Of ApplicationInfo)()
Dim info1 As New ApplicationInfo()
info1.Name = "Large Collider"
info1.Author = "C.E.R.N."
info1.IconPath = "img/Atom.png"
result.Add(info1)
Dim info2 As New ApplicationInfo()
info2.Name = "Paintbrush"
info2.Author = "Imagine Inc."
info2.IconPath = "img/Brush.png"
result.Add(info2)
Dim info3 As New ApplicationInfo()
info3.Name = "Lively Calendar"
info3.Author = "Control AG"
info3.IconPath = "img/CalendarEvents.png"
result.Add(info3)
Dim info4 As New ApplicationInfo()
info4.Name = "Fire Burning ROM"
info4.Author = "The CD Factory"
info4.IconPath = "img/CDBurn.png"
result.Add(info4)
Dim info5 As New ApplicationInfo()
info5.Name = "Fav Explorer"
info5.Author = "Star Factory"
info5.IconPath = "img/favorites.png"
result.Add(info5)
Dim info6 As New ApplicationInfo()
info6.Name = "IE Fox"
info6.Author = "Open Org"
info6.IconPath = "img/Connected.png"
result.Add(info6)
Dim info7 As New ApplicationInfo()
info7.Name = "Charting"
info7.Author = "AA-AZ inc"
info7.IconPath = "img/ChartDot.png"
result.Add(info7)
Dim info8 As New ApplicationInfo()
info8.Name = "SuperPlay"
info8.Author = "EB Games"
info8.IconPath = "img/Games.png"
result.Add(info8)
Return result
End Function
End Class
Then we need to define our ListBoxes with suitable ItemTemplates. We also enable dragging the ListBoxItems (through style) and allow drop to each of the ListBoxes (through setting AllowDrop property):
Example 2: Define ListBoxes, style and DataTemplate
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="telerik:DragDropManager.AllowCapturedDrag" Value="True"></Setter>
</Style>
<DataTemplate x:Key="ApplicationTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding IconPath}"/>
<TextBlock Margin="5" Text="{Binding Name}" VerticalAlignment="Center"></TextBlock>
</StackPanel>
</DataTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListBox x:Name="ApplicationList" ItemTemplate="{StaticResource ApplicationTemplate}" AllowDrop="True"/>
<ListBox x:Name="MyAppList" Background="Gray" Grid.Column="1"
ItemTemplate="{StaticResource ApplicationTemplate}" AllowDrop="True"/>
</Grid>
To use the DragDropManager and its components in XAML you have to declare the following namespace: xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
Afterwards we need to set the ItemsSource of the controls:
Example 3: Set ItemsSource
ApplicationList.ItemsSource = ApplicationInfo.GenerateApplicationInfos();
MyAppList.ItemsSource = new ObservableCollection<ApplicationInfo>();
ApplicationList.ItemsSource = ApplicationInfo.GenerateApplicationInfos()
MyAppList.ItemsSource = New ObservableCollection(Of ApplicationInfo)()
Example 4: Attach Drag-Drop event handlers
DragDropManager.AddDragInitializeHandler(ApplicationList, OnDragInitialize);
DragDropManager.AddDragInitializeHandler(MyAppList, OnDragInitialize);
DragDropManager.AddGiveFeedbackHandler(ApplicationList, OnGiveFeedback);
DragDropManager.AddGiveFeedbackHandler(MyAppList, OnGiveFeedback);
DragDropManager.AddDragDropCompletedHandler(ApplicationList, OnDragCompleted);
DragDropManager.AddDragDropCompletedHandler(MyAppList, OnDragCompleted);
DragDropManager.AddDropHandler(ApplicationList, OnDrop);
DragDropManager.AddDropHandler(MyAppList, OnDrop);
DragDropManager.AddDragInitializeHandler(ApplicationList, New DragInitializeEventHandler(AddressOf OnDragInitialize))
DragDropManager.AddDragInitializeHandler(MyAppList, New DragInitializeEventHandler(AddressOf OnDragInitialize))
DragDropManager.AddGiveFeedbackHandler(ApplicationList, New GiveFeedbackEventHandler(AddressOf OnGiveFeedback))
DragDropManager.AddGiveFeedbackHandler(MyAppList, New GiveFeedbackEventHandler(AddressOf OnGiveFeedback))
DragDropManager.AddDragDropCompletedHandler(ApplicationList, New DragDropCompletedEventHandler(AddressOf OnDragDropCompleted))
DragDropManager.AddDragDropCompletedHandler(MyAppList, New DragDropCompletedEventHandler(AddressOf OnDragDropCompleted))
DragDropManager.AddDropHandler(ApplicationList, New DragEventHandler(AddressOf OnDrop))
DragDropManager.AddDropHandler(MyAppList, New DragEventHandler(AddressOf OnDrop))
For more information about the available events, check out the Events article.
Then on DragInitialize we define the data that will be dragged as well as the visual representation. We also set DragDropEffects to all to allow drop on all scenarios.
Example 5: Implement OnDragInitialize
private void OnDragInitialize(object sender, DragInitializeEventArgs args)
{
args.AllowedEffects = DragDropEffects.All;
var payload = DragDropPayloadManager.GeneratePayload(null);
var data = ((FrameworkElement)args.OriginalSource).DataContext;
payload.SetData("DragData", data);
args.Data = payload;
args.DragVisual = new ContentControl { Content = data, ContentTemplate = LayoutRoot.Resources["ApplicationTemplate"] as DataTemplate };
}
Private Sub OnDragInitialize(ByVal sender As Object, ByVal args As DragInitializeEventArgs)
args.AllowedEffects = DragDropEffects.All
Dim payload = DragDropPayloadManager.GeneratePayload(Nothing)
Dim data = CType(args.OriginalSource, FrameworkElement).DataContext
payload.SetData("DragData", data)
args.Data = payload
args.DragVisual = New ContentControl With {.Content = data, .ContentTemplate = TryCast(LayoutRoot.Resources("ApplicationTemplate"), DataTemplate)}
End Sub
We also set mouse cursor to be arrow:
Example 6: Implement OnGiveFeedback
private void OnGiveFeedback(object sender, Telerik.Windows.DragDrop.GiveFeedbackEventArgs args)
{
args.SetCursor(Cursors.Arrow);
args.Handled = true;
}
Private Sub OnGiveFeedback(sender As Object, args As Telerik.Windows.DragDrop.GiveFeedbackEventArgs)
args.SetCursor(Cursors.Arrow)
args.Handled = True
End Sub
Finally, we add logic, that will be executed when drag and drop operations finish:
Example 7: Implement OnDrop
private void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs args)
{
var data = ((DataObject)args.Data).GetData("DragData");
((IList)(sender as ListBox).ItemsSource).Add(data);
}
public void OnDragCompleted(object sender, Telerik.Windows.DragDrop.DragDropCompletedEventArgs args)
{
var data = DragDropPayloadManager.GetDataFromObject(args.Data, "DragData");
((IList)(sender as ListBox).ItemsSource).Remove(data);
}
Private Sub OnDrop(ByVal sender As Object, ByVal args As Telerik.Windows.DragDrop.DragEventArgs)
Dim data = CType(args.Data, DataObject).GetData("DragData")
CType((TryCast(sender, ListBox)).ItemsSource, IList).Add(data)
End Sub
Public Sub OnDragCompleted(ByVal sender As Object, ByVal args As Telerik.Windows.DragDrop.DragDropCompletedEventArgs)
Dim data = DragDropPayloadManager.GetDataFromObject(args.Data, "DragData")
CType((TryCast(sender, ListBox)).ItemsSource, IList).Remove(data)
End Sub
Figure 1: Drag between ListBoxes
By default the DragDropManager shows the drag visual in a separate window. Since the 2018.3.1112 internal build version, you have the option to set the UseAdornerLayer property of the DragDropManager. After this property is set to True, the drag visual will be shown in the AdornerLayer of the MainWindow.