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

Drag and drop between treeviews

5 Answers 113 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Christian Burkhardt
Top achievements
Rank 1
Christian Burkhardt asked on 21 Jul 2011, 10:02 AM
Hi Telerik,

I have a user control with a RadTreeView which is open in multiple docking panes.
The user can  drag nodes, between the trees of the floating panes.

Since I reuse the usercontrol with the RadTreeView, when doing a drag and drop the same PreviewDragEnded event handler is called for both the source tree & target tree.
First the PreviewDragEnded event of the source tree from which the node is being dragged is called.
Next the PreviewDragEnded event of the target tree onto which the item is being dropped is called.

I have some questions in the code below:
//How do I know that this is the event of the source tree from which the item is dragged,
      and remove the item from the viewmodel (datacontext) items? 
//How do I know that this is the event of the target tree in which the item is dropped and
      add the item to the view model (datacontext)?
//How can I get a reference to both source tree datacontext, target tree datacontext in here,
      so I can call Remove, Add methods on them?

Please keep in mind that I need to know also the DropPosition, and Item onto which is being dropped.
Also, I can't use the default behavior of RadTreeView since I need to call Add/Remove methods on my viewmodel explicitly that do more processing than just adding/removing to a collection.
Also I am required to allow the user to re-order chapters using drag & drop, in the RadTreeView. 
How can I detect when I'm in a self-drag & drop scenario?

 One thought, crossing my mind was using sourceTree != e.TargetDropItem.ParentTree, but the problem is that, if I drop at the end of a tree, then e.TargetDropItem is null.


private void chaptersTree_PreviewDragEnded(object sender, RadTreeViewDragEndedEventArgs e)
       {
           //Get the RadTreeView
           RadTreeView sourceTree = e.OriginalSource as RadTreeView;
           //Get the dragged DataItem
           Chapter draggedDataItem = e.DraggedItems[0] as Chapter;
           RadTreeViewItem destinationItem = e.TargetDropItem;
 
 
           //How do I know that this is the event of the source tree from which the item is dragged, and remove the item from the viewmodel items?
           //How do I know that this is the event of the target tree in which the item is dropped?
           //How can I get a reference to both source tree datacontext, target tree datacontext in here, so I can call Remove, Add methods on them?
 
           e.Handled = true;
      }


5 Answers, 1 is accepted

Sort by
0
Christian Burkhardt
Top achievements
Rank 1
answered on 21 Jul 2011, 12:40 PM
One solution which might work I think is to use something like:

private RadTreeViewDragEndedEventArgs dragEndedEventArgs;
  
  
void TreeView_PreviewDragEnded(object sender, Telerik.Windows.Controls.RadTreeViewDragEndedEventArgs e)
{
 this.dragEndedEventArgs = e;
    e.Handled = true;
}
  
  
private void OnDropInfo(object sender, DragDropEventArgs e)
{
    if (e.Options.Status == DragStatus.DropComplete)
    {
        //detecting node reordering
        bool isSelfDragDrop = false;
        RadTreeView sourceTree = (e.Options.Source as RadTreeViewItem).ParentTreeView;
        RadTreeView destinationTree = null;
        if (e.Options.Destination is RadTreeView)
        {
            destinationTree = e.Options.Destination as RadTreeView;
        } else if (e.Options.Destination is RadTreeViewItem)
        {
            destinationTree = (e.Options.Destination as RadTreeViewItem).ParentTreeView;
        }
                                                                               
        if ((sourceTree == null || destinationTree == null) || (this.dragEndedEventArgs == null))
        {
            return; //this should not normally happen if we allow drag & drop just between trees.
        }
  
  
        if (sourceTree == destinationTree)
        {
            isSelfDragDrop = true;
        }
  
  
        //Get the drop position
        DropPosition dropPosition = this.dragEndedEventArgs.DropPosition;
        //Get the dragged DataItem
        DataItem draggedDataItem = this.dragEndedEventArgs.DraggedItems[0] as DataItem;
        //Get the destination DataItem
                DataItem destinationItem = null;
                bool isDroppedAtEndOfTree = false;
                if (e.Options.Destination is RadTreeViewItem)
                {
                    destinationItem = this.dragEndedEventArgs.TargetDropItem.Item as DataItem;   
                } else if (e.Options.Destination is RadTreeView && insertPosition == TreeInsertPosition.Inside)
                {
                    //if we're here, it means that we're trying to make the dragged element the last node of the tree
                    //in that case, the destination is not the last tree node, with DropPosition=After,
                    //instead it is the RadTreeView itself with DropPosition = Inside.
                    isDroppedAtEndOfTree = true;
                }  
  
        var sourceViewModel = sourceTree.DataContext;
        var parentViewModel = destinationTree.DataContext;
  
  
        //remove from sourceViewModel...
          
        //add to destinationViewModel...
    }
}

The OnDropInfo only gets called once, for the tree onto which is dropped, even though the source tree is subscribed to the same event using the same event handler.

What I don't like about the solution, is that into the OnDropInfo I don't have access to the drop position, and I have to "share" the EventArgs of the PreviewDragEnded.

Feels like a hack, but do you have any better ideas on how to access the DropPosition in the OnDropInfo event?
If not, do you see any scenarios which this solution doesn't cover?
0
Petar Mladenov
Telerik team
answered on 26 Jul 2011, 01:18 PM
Hi Christian Burkhardt,

 The RadTreeViewItem exposes DropPosition property. So you can do like so in the DropInfo:

DropPosition dropPos = (e.Options.Destination as RadTreeViewItem).DropPosition;
Please let us know if this works for you.Regards,
Petar Mladenov
the Telerik team

Register for the Q2 2011 What's New Webinar Week. Mark your calendar for the week starting July 18th and book your seat for a walk through of all the exciting stuff we will ship with the new release!

0
James
Top achievements
Rank 1
answered on 01 Aug 2011, 05:02 PM
Hi Petar,

I've tracked this thread, as I have the same challenge. Is using the drag-drop manager the only way of doing this? (i.e. there is no way of knowing in PreviewDragEnded which tree you are dealing with (when the TargetDropItem is null)?

Thanks, James.
0
James
Top achievements
Rank 1
answered on 02 Aug 2011, 01:54 PM
Sorry - please ignore that question. Of course, when reordering the TargetDropItem can't be null...!

James.
0
Christian Burkhardt
Top achievements
Rank 1
answered on 04 Aug 2011, 08:08 PM
Hi Telerik,
Yes this works, thank you for the solution.
Tags
TreeView
Asked by
Christian Burkhardt
Top achievements
Rank 1
Answers by
Christian Burkhardt
Top achievements
Rank 1
Petar Mladenov
Telerik team
James
Top achievements
Rank 1
Share this question
or