This is a migrated thread and some comments may be shown as answers.

Problems with DragDropManager on TreeView

3 Answers 247 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Alexander
Top achievements
Rank 1
Alexander asked on 15 Jul 2014, 09:07 AM
Hello,

I'm trying to implement some Drag and Drop functionality on an inhomogenious RadTreeView. I started from the "Tree to Grid Drag" Demo project.
There you define some DropIndicationDetails to display the input location. However I don't like this style (and the fact that I have to create a datatemplate for drag and drop) - which is why I want to use the default drag/drop appearance with the Windows 8 style (see attached image).

I therefore created a simplified version of the TreeViewDragDopBehavior:

public class TreeViewDragDropBehavior
{
    public static bool GetIsEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsEnabledProperty);
    }
 
    public static void SetIsEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsEnabledProperty, value);
    }
 
    public static readonly DependencyProperty IsEnabledProperty =
        DependencyProperty.RegisterAttached("IsEnabled", typeof(bool), typeof(TreeViewDragDropBehavior),
            new PropertyMetadata(OnIsEnabledPropertyChanged));
 
    public static void OnIsEnabledPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        if (true.Equals(e.NewValue))
        {
            Initialize(dependencyObject as RadTreeView);
        }
        else
        {
            CleanUp(dependencyObject as RadTreeView);
        }
    }
 
    protected static void Initialize(RadTreeView treeView)
    {
        DragDropManager.AddDragInitializeHandler(treeView, OnDragInitialize, true);
        DragDropManager.AddGiveFeedbackHandler(treeView, OnGiveFeedback, true);
        DragDropManager.AddDragDropCompletedHandler(treeView, OnDragDropCompleted, true);
        DragDropManager.AddDropHandler(treeView, OnDrop, true);
 
        treeView.ItemPrepared += AssociatedObject_ItemPrepared;
    }
 
    protected static void CleanUp(RadTreeView treeView)
    {
        DragDropManager.RemoveDragInitializeHandler(treeView, OnDragInitialize);
        DragDropManager.RemoveGiveFeedbackHandler(treeView, OnGiveFeedback);
        DragDropManager.RemoveDragDropCompletedHandler(treeView, OnDragDropCompleted);
        DragDropManager.RemoveDropHandler(treeView, OnDrop);
    }
 
    static void AssociatedObject_ItemPrepared(object sender, RadTreeViewItemPreparedEventArgs e)
    {
        DragDropManager.RemoveDragOverHandler(e.PreparedItem, OnItemDragOver);
        DragDropManager.AddDragOverHandler(e.PreparedItem, OnItemDragOver);
    }
 
    private static void OnDragInitialize(object sender, DragInitializeEventArgs e)
    {
        var treeViewItem = e.OriginalSource as RadTreeViewItem ?? (e.OriginalSource as FrameworkElement).ParentOfType<RadTreeViewItem>();
        var data = treeViewItem != null ? treeViewItem.Item : (sender as RadTreeView).SelectedItem;
 
        var payload = DragDropPayloadManager.GeneratePayload(null);
        payload.SetData("DraggedData", data);
 
        e.Data = payload;
        e.DragVisualOffset = e.RelativeStartPoint;
        e.AllowedEffects = DragDropEffects.All;
    }
 
    private static void OnGiveFeedback(object sender, Telerik.Windows.DragDrop.GiveFeedbackEventArgs e)
    {
        e.SetCursor(Cursors.Arrow);
        e.Handled = true;
    }
 
    private static void OnDragDropCompleted(object sender, DragDropCompletedEventArgs e)
    {
        e.Handled = true;
    }
 
    private static void OnDrop(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
    {
    }
 
    private static void OnItemDragOver(object sender, Telerik.Windows.DragDrop.DragEventArgs e)
    {
        e.Effects = DragDropEffects.All;
        e.Handled = true;
    }
}

However, although I set 'e.Effects = DragDropEffects.All' in the OnItemDragOver method, it always shows the forbidden icon (in the OnDrop method, the Effects are correct). If I do not set the payload (by simply commenting out this line in the OnDragInitialize method), I get the expected appearance as in the screen shot. However - the OnItemDragOver method is never called. Therefore, I don't have any possibility to manually override the e.Effects settings.

Is there any way to influence the effects if I dont set the payload manually? Or alternatively to show the correect drop position without having handle it manually?

By the way - there is a very severy memory leak in your original example! You store the TreeViewDragDropBehavior in a static dictionary, together with the RadTreeView. This keeps the TreeViewDragDropBehavior, its associated RadTreeView, it's TreeViewItems and the corresponding data alive forever.

Alexander Müller

3 Answers, 1 is accepted

Sort by
0
Petar Mladenov
Telerik team
answered on 16 Jul 2014, 07:22 AM
Hi Alexander,

The example you use as a base is a bit old and we encourage you to use the built in DragDrop of the RadTreeView. You can use TreeView's DragDrop sample in our Demos and the following support resources:
RadTreeView DragDrop overview
RadTreeView DragDrop How Tos - Drag Between 2 TreeViews
It is in our plans to update / refactor this sample to not use TreeViewDragDropBehavior but only the DragDropManager events - this would minimize the code of the sample. With this refactoring we will also remove the mentioned memory leaks.

Please let us know if the provided resources move you in the right direction.

Regards,
Petar Mladenov
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
0
Alexander
Top achievements
Rank 1
answered on 16 Jul 2014, 08:27 AM
Thanks for the info.

I was missing the TreeViewDragDropOptions. By calling setting the DropAction and calling UpdateDragVisual(), I managed to show the correct drag sign. However, setting the DropPosition does not seem to have an effect? I expected that the DropPreviewLine would update/hide accordingly.

Just a note: It would be nice to have some information which sample are up-to-date. You suggest to use the built-in DragDrop of the RadTreeView, but the "RadTreeView DragDrop overview" linked by you uses some deprecated events like PreviewDragStarted...

Alexander Müller
0
Petar Mladenov
Telerik team
answered on 18 Jul 2014, 07:46 AM
Hello Alexander,

You can try invoking the UpdatedDropPreviewLine method of the RadTreeView. If this does not help, you can isolate your issue in a sample project, send it in a new support thread and we will be better able to investigate it and advice you accordingly.

I believe in the mentioned article there are Important Notes on every place where a Legacy code is used.
Also there are notes prompting the users to use only the New mode.
 Please let us know if we have missed something to note in the article and we will update it.

Regards,
Petar Mladenov
Telerik
 
Check out Telerik Analytics, the service which allows developers to discover app usage patterns, analyze user data, log exceptions, solve problems and profile application performance at run time. Watch the videos and start improving your app based on facts, not hunches.
 
Tags
TreeView
Asked by
Alexander
Top achievements
Rank 1
Answers by
Petar Mladenov
Telerik team
Alexander
Top achievements
Rank 1
Share this question
or