TreeView Drag Drop in Silverlight

Posted by: Suprotim Agarwal , on 5/19/2010, in Category Silverlight 2, 3, 4 and 5
Views: 51458
Abstract: I have seen plenty of questions around drag-drop operations within a TreeView and I thought of dedicating a post to it. This article shows you how easy it is now to do a Drag Drop operation on a TreeView in Silverlight
I have seen plenty of questions around drag-drop operations within a TreeView and I thought of dedicating a post to it. Now usually when one thinks of implementing a Drag Drop operation on a TreeView, there are a couple of events like the DragEnter, DragLeave, DragOver and Drop that are to be raised and handled. In some cases, you must also cancel the drag-n-drop operation if the drop is invalid. Overall, this looks like a lot of work for a developer who wants to quickly implement drag-n-drop functionality on his/her controls.
With the addition of the drag-drop targets for controls like the TreeView (and some others like the ListBox, DataGrid and DataPointSeries), doing a drag and drop operation in a TreeView is a cakewalk. Here’s a simple example:
Note: Make sure you have added a reference to the System.Windows.Toolkit. You can download the latest Silverlight toolkit over here
<UserControl
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
    x:Class="SilverlightDragDropTreeView.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="250" d:DesignWidth="300">
    <Canvas x:Name="LayoutRoot">
        <toolkit:TreeViewDragDropTarget AllowDrop="True" HorizontalContentAlignment="Stretch">
            <sdk:TreeView Height="250" >
                <sdk:TreeViewItem Header="Permanent">
                    <sdk:TreeViewItem Header="Jill"/>
                    <sdk:TreeViewItem Header="Yahana"/>
                    <sdk:TreeViewItem Header="Kapil"/>
                </sdk:TreeViewItem>
                <sdk:TreeViewItem Header="Temporary">
                    <sdk:TreeViewItem Header="Matthew"/>
                    <sdk:TreeViewItem Header="Sarak"/>
                    <sdk:TreeViewItem Header="Jack"/>
                </sdk:TreeViewItem>
            </sdk:TreeView>
        </toolkit:TreeViewDragDropTarget>
    </Canvas>
</UserControl>
 
As you can see, the TreeView control is wrapped inside a TreeViewDragDropTarget which has the UIElement.AllowDrop property set to True. The UIElement.AllowDrop property determines whether this UIElement can be a drop target for purposes of Silverlight drag-and-drop operations. Setting this property to true enables it to raise or handle events like DragEnter, DragLeave, DragOver and Drop.
That is all that is required to enable Drag-Drop operations on a TreeView. Run the code and you will see that you can drop items between the Permanent and Temporary Categories
Temporary
After dragging and dropping ‘yahana’ from Permanent to Temporary
Permanant
Binding the TreeView with a Parent-Child Collection Object
As you can observe, to keep this article simple and to the point, I have hardcoded the TreeViewItem’s in the markup. In a real world application, you will rarely do that. Instead you would want to bind a custom collection of objects to the TreeView.
Let’s walkthrough the logical steps to bind the TreeView to a collection of objects. This example assumes that there are two collections:
-      EmployeeCategory collection containing a EmpCategoryName property with two values, Permanent and Temporary
-      Employee collection within each EmployeeCategory containing EmployeeName field
Here’s some ‘psuedocode’ of what the EmployeeCategory class would look like
public class EmployeeCategory implements INotifyPropertyChanged
{
     public string EmpCategoryName { get; set; } // onPropertyChanged
     public List<Employee> _employees { get; set; } // onPropertyChanged
So each parent level of the TreeView will be bound to the EmpCategoryName property from the EmployeeCategory, whereas the second level will display the EmployeeName in each EmployeeCategory collection.  
To bind this collection to the TreeView, we will use a TreeView.ItemTemplate. Since we are using a Parent-Child relationship here, we will use two HierarchicalDataTemplate templates. Here’s how the markup would look like
<toolkit:TreeViewDragDropTarget AllowDrop="True" VerticalContentAlignment="Stretch">
        <toolkit:TreeViewDragDropTarget.Resources>
 
            <sdk:HierarchicalDataTemplate  x:Key="EmpCategory"
ItemsSource="{Binding Employee}" ItemTemplate="{StaticResource EmpNames}">
                 <TextBlock Text="{Binding EmpCategoryName}"/>
            </sdk:HierarchicalDataTemplate>
 
            <sdk:HierarchicalDataTemplate  x:Key="EmpNames"
                <TextBlock Text="{Binding EmployeeName}"/>
            </sdk:HierarchicalDataTemplate>
 
        </toolkit:TreeViewDragDropTarget.Resources>
 
        <sdk:TreeView x:Name="tView" ItemTemplate="{StaticResource EmpCategory}"
        Height="250" >
        </sdk:TreeView>
</toolkit:TreeViewDragDropTarget>
 
The data can be pulled using a WCF service which will query the EmployeeCategory and Employee classes and bind it to the TreeView. I hope these steps will guide you how to bind the TreeView to a custom collection object. Let me know if you need a complete article on this with the WCF service implementation and I will write one for you.
I hope this article was useful and I thank you for viewing it. The entire source code of this article can be downloaded over here
Give me a +1 if you think it was a good article. Thanks!
Recommended Articles
Suprotim Agarwal, ASP.NET Architecture MVP, MCSD, MCAD, MCDBA, MCSE, is the CEO of A2Z Knowledge Visuals Pvt. He primarily works as an Architect Consultant and provides consultancy on how to design and develop .NET centric database solutions.

Suprotim is the founder and primary contributor to DotNetCurry, SQLServerCurry and DevCurry. He has also written an EBook 51 Recipes using jQuery with ASP.NET Controls.

Follow him on twitter @suprotimagarwal


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Mickey on Wednesday, May 19, 2010 5:40 AM
(taking a bow) Man you write so simple! It gets into my head instantly :)
Comment posted by Clay Fowler on Sunday, February 20, 2011 7:15 PM
What events are you supposed to bind to in order to make drag and drop work on a data bound TreeView? Dragging works on my TreeView but dropping has no effect (nodes don't move).
Comment posted by Ruchita on Wednesday, March 30, 2011 12:54 AM
Thanks Suprotim !
code is easy but i was unaware of this silverlight control...
now i got its very easy to drag and drop tree view nodes .
can i use the same for my tree view nodes coming from database ?
thanks for sharing  ...
Comment posted by Suprotim Agarwal on Wednesday, March 30, 2011 8:27 PM
Yes Ruchita, it will work with data coming from any datasource. The drag drop operation is done client side
Comment posted by Ruchita on Thursday, March 31, 2011 2:05 AM
Hi Suprotim !
ur code is working fine for static tree view items .
can u pls tell me how can i add data from my sql server data base ?
my table contain id and parentid coloumn.
parentid is the parent node in tree view .
root node will contain parent id as 0
so all child node will come under there parent id , and when i drag and drop this child id to other parent node .
it shud be update in data base table too.
pls help me .
i hav to finish this task by eod .
thanks in advance.
Comment posted by Ruchita on Friday, April 1, 2011 12:24 AM
Hi Suprotim !
I hav done my task , only the updation in db is pending.


Comment posted by Suprotim Agarwal on Saturday, April 2, 2011 6:27 AM
Good job Ruchita. I am sure you will figure out how to update the db. You need to read the serialized value and update the DB. If you google it out, there are plenty of articles written on the same.
Comment posted by Harisha on Monday, April 4, 2011 4:47 PM
Hi Suprotim
I was running in this weird issue when I tried to use the silverlight dragdragtarget with the treeview with connecting lines, here;'s the issue:
hen I try to expand the nodes clicking on the + on the nodes it is trigerring a drag even on the node , tried to cancel the drag even but am not sure if I am doing it right?

Here is the code:

<toolkit:TreeViewDragDropTarget AllowDrop="true" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" ItemDragStarting="TreeViewDragDropTarget_ItemDragStarting" ItemDragCompleted="TreeViewDragDropTarget_ItemDragCompleted" ItemDroppedOnTarget="TreeViewDragDropTarget_ItemDroppedOnTarget" Drop="TreeViewDragDropTarget_Drop">
                   <sdk:TreeView  Name="TVHierarchy" Width="Auto" Height="auto" Background="WhiteSmoke" AllowDrop="False"/>
                   </toolkit:TreeViewDragDropTarget>  

Please let me know how to handle the issue
Comment posted by Sathis on Tuesday, September 20, 2011 2:25 PM
i have seen the example of Drag and Drop Very Nice Article. Can you tell how to restrict adding inside the Child Node.It will be helpful.
Comment posted by Ganesh on Monday, February 27, 2012 3:45 AM
Great Article.
It was really useful to me.
Not only this but all of ur posts were useful to me.
Do post a lot of articles.

Thanks..

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel