I have a treeview and a gridview. The user should be able to move elements from the gridview to the treeview and change the effect of the drag&drop action by using the shift or control key (like in Windows Explorer).
In the GiveFeedback event the effect is set according to the pressed key and also the visualization shows the expected behavior. But in the Drop event (on the treeview) and in the DragDropCompleted event (on the gridview) the effect is set to All, therefore I'm not able to decide if I have to remove the Element from the current list.
Am I missing something or is there a Bug in the library?
XAML:
<
Window
x:Class
=
"DragAndDropToTreeView.MainWindow"
xmlns:local
=
"clr-namespace:DragAndDropToTreeView"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
Title
=
"MainWindow"
Width
=
"623"
Height
=
"461"
>
<
Grid
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
=
"1*"
/>
<
ColumnDefinition
Width
=
"2*"
/>
</
Grid.ColumnDefinitions
>
<
telerik:RadTreeView
AllowDrop
=
"True"
ItemsSource
=
"{Binding Folders}"
SelectedItem="{Binding SelectedFolder,
Mode
=
TwoWay
}"
SelectionMode
=
"Single"
>
<
telerik:RadTreeView.Resources
>
<
HierarchicalDataTemplate
DataType
=
"{x:Type local:Folder}"
ItemsSource
=
"{Binding Children}"
>
<
Grid
VerticalAlignment
=
"Center"
>
<
TextBlock
VerticalAlignment
=
"Center"
Text
=
"{Binding Name}"
local:TreeItemDropBehavior.IsEnabled
=
"True"
/>
</
Grid
>
</
HierarchicalDataTemplate
>
</
telerik:RadTreeView.Resources
>
</
telerik:RadTreeView
>
<
telerik:RadGridView
Grid.Column
=
"1"
AllowDrop
=
"True"
AutoGenerateColumns
=
"False"
CanUserFreezeColumns
=
"False"
CanUserReorderColumns
=
"False"
CanUserResizeColumns
=
"False"
FontSize
=
"12"
IsFilteringAllowed
=
"False"
IsReadOnly
=
"True"
ItemsSource
=
"{Binding SelectedFolder.Elements}"
RowHeight
=
"32"
RowIndicatorVisibility
=
"Collapsed"
SelectionMode
=
"Multiple"
ShowGroupPanel
=
"False"
local:GridViewDragDropBehavior.IsEnabled
=
"True"
telerik:DragDropManager.AllowCapturedDrag
=
"True"
telerik:DragDropManager.AllowDrag
=
"True"
>
<
telerik:RadGridView.Resources
>
<
ResourceDictionary
>
<
ResourceDictionary.MergedDictionaries
>
<
ResourceDictionary
>
<
DataTemplate
x:Key
=
"DraggedItemTemplate"
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
TextBlock
Text
=
"Dragging: "
/>
<
TextBlock
FontWeight
=
"Bold"
Text
=
"{Binding CurrentDraggedItems.Count}"
/>
<
TextBlock
Text
=
" Element(s)"
/>
</
StackPanel
>
</
DataTemplate
>
</
ResourceDictionary
>
</
ResourceDictionary.MergedDictionaries
>
</
ResourceDictionary
>
</
telerik:RadGridView.Resources
>
<
telerik:RadGridView.Columns
>
<
telerik:GridViewDataColumn
Width
=
"100"
DataMemberBinding
=
"{Binding Name}"
Header
=
"Name"
/>
<
telerik:GridViewDataColumn
Width
=
"250"
DataMemberBinding
=
"{Binding Description}"
Header
=
"Description"
/>
</
telerik:RadGridView.Columns
>
</
telerik:RadGridView
>
</
Grid
>
</
Window
>
GridViewDragDropBehavior.cs:
using
System.Collections;
using
System.Collections.Generic;
using
System.Diagnostics;
using
System.Windows;
using
System.Windows.Input;
using
Telerik.Windows.Controls;
using
Telerik.Windows.DragDrop;
using
Telerik.Windows.DragDrop.Behaviors;
using
GiveFeedbackEventArgs = Telerik.Windows.DragDrop.GiveFeedbackEventArgs;
namespace
DragAndDropToTreeView
{
public
class
GridViewDragDropBehavior
{
public
RadGridView AssociatedControl {
get
;
set
; }
private
static
readonly
Dictionary<RadGridView, GridViewDragDropBehavior> Instances;
static
GridViewDragDropBehavior()
{
Instances =
new
Dictionary<RadGridView, GridViewDragDropBehavior>();
}
public
static
bool
GetIsEnabled(DependencyObject obj)
{
return
(
bool
)obj.GetValue(IsEnabledProperty);
}
public
static
void
SetIsEnabled(DependencyObject obj,
bool
value)
{
GridViewDragDropBehavior behavior = GetAttachedBehavior(obj
as
RadGridView);
behavior.AssociatedControl = obj
as
RadGridView;
if
(value)
{
behavior.Initialize();
}
else
{
behavior.CleanUp();
}
obj.SetValue(IsEnabledProperty, value);
}
public
static
readonly
DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled"
,
typeof
(
bool
),
typeof
(GridViewDragDropBehavior),
new
PropertyMetadata(OnIsEnabledPropertyChanged));
public
static
void
OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
SetIsEnabled(dependencyObject, (
bool
)e.NewValue);
}
private
static
GridViewDragDropBehavior GetAttachedBehavior(RadGridView gridView)
{
if
(!Instances.ContainsKey(gridView))
{
Instances[gridView] =
new
GridViewDragDropBehavior { AssociatedControl = gridView };
}
return
Instances[gridView];
}
protected
virtual
void
Initialize()
{
UnsubscribeFromDragDropEvents();
SubscribeToDragDropEvents();
}
protected
virtual
void
CleanUp()
{
UnsubscribeFromDragDropEvents();
}
private
void
SubscribeToDragDropEvents()
{
DragDropManager.AddDragInitializeHandler(AssociatedControl, OnDragInitialize);
DragDropManager.AddGiveFeedbackHandler(AssociatedControl, OnGiveFeedback);
DragDropManager.AddDragDropCompletedHandler(AssociatedControl, OnDragDropCompleted);
DragDropManager.AddDragOverHandler(AssociatedControl, OnDragOver);
}
private
void
UnsubscribeFromDragDropEvents()
{
DragDropManager.RemoveDragInitializeHandler(AssociatedControl, OnDragInitialize);
DragDropManager.RemoveGiveFeedbackHandler(AssociatedControl, OnGiveFeedback);
DragDropManager.RemoveDragDropCompletedHandler(AssociatedControl, OnDragDropCompleted);
DragDropManager.RemoveDragOverHandler(AssociatedControl, OnDragOver);
}
private
void
OnDragInitialize(
object
sender, DragInitializeEventArgs e)
{
DropIndicationDetails details =
new
DropIndicationDetails();
var gridView = sender
as
RadGridView;
details.DragSource = gridView.ItemsSource;
var items = gridView.SelectedItems;
details.CurrentDraggedItems = items;
IDragPayload dragPayload = DragDropPayloadManager.GeneratePayload(
null
);
dragPayload.SetData(
"DraggedData"
, items);
dragPayload.SetData(
"DropDetails"
, details);
e.Data = dragPayload;
e.DragVisual =
new
DragVisual { Content = details, ContentTemplate = AssociatedControl.Resources[
"DraggedItemTemplate"
]
as
DataTemplate };
e.DragVisualOffset =
new
Point(e.RelativeStartPoint.X + 10, e.RelativeStartPoint.Y);
e.AllowedEffects = DragDropEffects.All;
}
private
void
OnGiveFeedback(
object
sender, GiveFeedbackEventArgs e)
{
Debug.WriteLine(
"GridViewDragDropBehavior.OnGiveFeedback {0}"
, e.Effects);
e.SetCursor(Cursors.Arrow);
e.Handled =
true
;
}
private
void
OnDragDropCompleted(
object
sender, DragDropCompletedEventArgs e)
{
Debug.WriteLine(
"GridViewDragDropBehavior.OnDragDropCompleted: {0}"
, e.Effects);
var data = DragDropPayloadManager.GetDataFromObject(e.Data,
"DraggedData"
)
as
IList;
var details = DragDropPayloadManager.GetDataFromObject(e.Data,
"DropDetails"
);
Debug.WriteLine(e.Effects);
// Remove Element from source list if drag drop effect is move
/*if (e.Effects == DragDropEffects.Move)
{
var collection = (details as DropIndicationDetails).DragSource as IList;
foreach(var element in data)
{
collection.Remove(element);
}
}*/
}
private
void
OnDragOver(
object
sender, Telerik.Windows.DragDrop.DragEventArgs e)
{
Debug.WriteLine(
"GridViewDragDropBehavior.OnDragOver: {0}"
, e.Effects);
e.Effects = DragDropEffects.None;
e.Handled =
true
;
}
}
}
TreeItemDropBehavior.cs:
using
System.Collections;
using
System.Collections.Generic;
using
System.Diagnostics;
using
System.Windows;
using
System.Windows.Input;
using
Telerik.Windows.Controls;
using
Telerik.Windows.DragDrop;
namespace
DragAndDropToTreeView
{
public
class
TreeItemDropBehavior
{
/// <summary>
/// AssociatedObject Property
/// </summary>
public
RadTreeViewItem AssociatedObject {
get
;
set
; }
private
static
readonly
Dictionary<RadTreeViewItem, TreeItemDropBehavior> Instances;
static
TreeItemDropBehavior()
{
Instances =
new
Dictionary<RadTreeViewItem, TreeItemDropBehavior>();
}
public
static
bool
GetIsEnabled(DependencyObject obj)
{
return
(
bool
)obj.GetValue(IsEnabledProperty);
}
public
static
void
SetIsEnabled(DependencyObject obj,
bool
value)
{
var treeViewItem = obj.ParentOfType<RadTreeViewItem>();
TreeItemDropBehavior behavior = GetAttachedBehavior(treeViewItem);
behavior.AssociatedObject = treeViewItem;
if
(value)
{
behavior.Initialize();
}
else
{
behavior.CleanUp();
}
obj.SetValue(IsEnabledProperty, value);
}
// Using a DependencyProperty as the backing store for IsEnabled. This enables animation, styling, binding, etc...
public
static
readonly
DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled"
,
typeof
(
bool
),
typeof
(TreeItemDropBehavior),
new
PropertyMetadata(OnIsEnabledPropertyChanged));
public
static
void
OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
SetIsEnabled(dependencyObject, (
bool
)e.NewValue);
}
private
static
TreeItemDropBehavior GetAttachedBehavior(RadTreeViewItem treeViewItem)
{
if
(!Instances.ContainsKey(treeViewItem))
{
Instances[treeViewItem] =
new
TreeItemDropBehavior { AssociatedObject = treeViewItem };
}
return
Instances[treeViewItem];
}
protected
virtual
void
Initialize()
{
DragDropManager.AddGiveFeedbackHandler(AssociatedObject, OnGiveFeedback);
DragDropManager.AddDropHandler(AssociatedObject, OnDrop);
}
protected
virtual
void
CleanUp()
{
DragDropManager.RemoveGiveFeedbackHandler(AssociatedObject, OnGiveFeedback);
DragDropManager.RemoveDropHandler(AssociatedObject, OnDrop);
}
private
void
OnGiveFeedback(
object
sender, Telerik.Windows.DragDrop.GiveFeedbackEventArgs e)
{
Debug.WriteLine(
"TreeItemDropBehavior.OnGiveFeedback {0}"
, e.Effects);
e.SetCursor(Cursors.Arrow);
e.Handled =
true
;
}
private
void
OnDrop(
object
sender, Telerik.Windows.DragDrop.DragEventArgs e)
{
Debug.WriteLine(
"TreeItemDropBehavior.OnDrop: {0}"
, e.Effects);
if
(e.Effects != DragDropEffects.None)
{
var destinationItem = (e.OriginalSource
as
FrameworkElement).ParentOfType<RadTreeViewItem>();
var data = DragDropPayloadManager.GetDataFromObject(e.Data,
"DraggedData"
)
as
IList;
var details = DragDropPayloadManager.GetDataFromObject(e.Data,
"DropDetails"
)
as
DropIndicationDetails;
if
(destinationItem !=
null
)
{
foreach
(var element
in
data)
{
(destinationItem.DataContext
as
Folder).Elements.Add(element
as
Element);
}
e.Handled =
true
;
}
}
}
}
}