Drag, Drop and Move Multiple Items from a ListView to a TreeView control

Posted by: Suprotim Agarwal , on 10/1/2008, in Category WinForms & WinRT
Views: 45462
Abstract: In this article, we will explore how to drag, drop and move multiple items from a ListView control to a TreeView. We will also use the GiveFeedback event to change the default cursor during the drag drop operation.
Drag, Drop and Move Multiple Items from a ListView to a TreeView control
 
In this short article, we will explore how to drag, drop and move multiple items from a ListView control to a TreeView. We will also use the GiveFeedback event to change the default cursor during the drag drop operation. I have kept the sample as simple as possible. Follow these steps:
Step 1: Open Visual Studio > File > New > Project. In the Project Types pane, choose the language of your choice (Visual C# or Visual Basic). In the Templates pane, choose Windows Application. Choose a name and location for the project and click OK.
Step 2: Drag and Drop a ListView and a TreeView control (listView1 and treeView1) to the form. In the Form_Load(), we will first load the ListView and the TreeView with some sample data. To enable drag and drop at runtime, we will be handling 3 events primarily during the entire drag drop operation. Let us quickly see what do these events do:
ListView_ItemDrag Event – this event is raised from the ListView control when the user starts to drag the ListView nodes
TreeView_DragEnter Event - this event is raised from the TreeView control when the items are dragged into the TreeView control's bounds
TreeView_DragDrop Event - this event is raised when a drag-and-drop operation is completed.
Step 3: Now add some code to the Form_Load event to pre-populate the ListView and TreeView as well as register the drag drop events
C#
private void Form1_Load(object sender, EventArgs e)
{
    listView1.ItemDrag += new ItemDragEventHandler(listView1_ItemDrag);
    treeView1.DragEnter += new DragEventHandler(treeView1_DragEnter);
    treeView1.DragDrop += new DragEventHandler(treeView1_DragDrop);
    PopulateListViewTreeView();
}
 
private void PopulateListViewTreeView()
{
    List<string> lst = new List<string>();
    lst.Add("Item1");
    lst.Add("Item2");
    lst.Add("Item3");
    lst.Add("Item4");
    lst.Add("Item5");
    lst.Add("Item6");
 
    // Populate ListView
    for (int i = 0; i < lst.Count; i++)
    {
        ListViewItem lvItem = new ListViewItem(lst[i].ToString());
        listView1.Items.Add(lvItem);
        lvItem.EnsureVisible();
    }
 
    // Populate TreeView
    for (int i = 0; i < lst.Count; i++)
    {
        TreeNode node = new TreeNode(lst[i].ToString());
        if (i % 2 == 0)
            treeView1.Nodes.Add(node);
        else
            treeView1.Nodes[0].Nodes.Add(node);
        node.EnsureVisible();
    }
    treeView1.ExpandAll();
    treeView1.AllowDrop = true;
}
VB.NET
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs)
      AddHandler listView1.ItemDrag, AddressOf listView1_ItemDrag
      AddHandler treeView1.DragEnter, AddressOf treeView1_DragEnter
      AddHandler treeView1.DragDrop, AddressOf treeView1_DragDrop
      PopulateListViewTreeView()
End Sub
 
Private Sub PopulateListViewTreeView()
      Dim lst As List(Of String) = New List(Of String)()
      lst.Add("Item1")
      lst.Add("Item2")
      lst.Add("Item3")
      lst.Add("Item4")
      lst.Add("Item5")
      lst.Add("Item6")
 
      ' Populate ListView
      For i As Integer = 0 To lst.Count - 1
            Dim lvItem As ListViewItem = New ListViewItem(lst(i).ToString())
            listView1.Items.Add(lvItem)
            lvItem.EnsureVisible()
      Next i
 
      ' Populate TreeView
      For i As Integer = 0 To lst.Count - 1
            Dim node As TreeNode = New TreeNode(lst(i).ToString())
            If i Mod 2 = 0 Then
                  treeView1.Nodes.Add(node)
            Else
                  treeView1.Nodes(0).Nodes.Add(node)
            End If
            node.EnsureVisible()
      Next i
      treeView1.ExpandAll()
      treeView1.AllowDrop = True
End Sub
Step 4: The next step is to add some code to respond to these event handlers
C#
private void listView1_ItemDrag(object sender, ItemDragEventArgs e)
{
    listView1.DoDragDrop(listView1.SelectedItems, DragDropEffects.Move);
}
 
private void treeView1_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(ListView.SelectedListViewItemCollection)))
        e.Effect = DragDropEffects.Move;
}
 
private void treeView1_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(ListView.SelectedListViewItemCollection).ToString(), false))
    {
        Point loc = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
        TreeNode destNode = ((TreeView)sender).GetNodeAt(loc);
        TreeNode tnNew;
 
        ListView.SelectedListViewItemCollection lstViewColl =
            (ListView.SelectedListViewItemCollection)e.Data.GetData(typeof(ListView.SelectedListViewItemCollection));
        foreach (ListViewItem lvItem in lstViewColl)
        {
            tnNew = new TreeNode(lvItem.Text);
            tnNew.Tag = lvItem;
 
            destNode.Nodes.Insert(destNode.Index + 1, tnNew);
            destNode.Expand();
            // Remove this line if you want to only copy items
            // from ListView and not move them
            lvItem.Remove();
        }
    }
}
VB.NET
Private Sub listView1_ItemDrag(ByVal sender As Object, ByVal e As ItemDragEventArgs)
      listView1.DoDragDrop(listView1.SelectedItems, DragDropEffects.Move)
End Sub
 
Private Sub treeView1_DragEnter(ByVal sender As Object, ByVal e As DragEventArgs)
      If e.Data.GetDataPresent(GetType(ListView.SelectedListViewItemCollection)) Then
            e.Effect = DragDropEffects.Move
      End If
End Sub
 
Private Sub treeView1_DragDrop(ByVal sender As Object, ByVal e As DragEventArgs)
      If e.Data.GetDataPresent(GetType(ListView.SelectedListViewItemCollection).ToString(), False) Then
            Dim loc As Point = (CType(sender, TreeView)).PointToClient(New Point(e.X, e.Y))
            Dim destNode As TreeNode = (CType(sender, TreeView)).GetNodeAt(loc)
            Dim tnNew As TreeNode
 
            Dim lstViewColl As ListView.SelectedListViewItemCollection = CType(e.Data.GetData(GetType(ListView.SelectedListViewItemCollection)), ListView.SelectedListViewItemCollection)
            For Each lvItem As ListViewItem In lstViewColl
                  tnNew = New TreeNode(lvItem.Text)
                  tnNew.Tag = lvItem
 
                  destNode.Nodes.Insert(destNode.Index + 1, tnNew)
                  destNode.Expand()
                  ' Remove this line if you want to only copy items
                  ' from ListView and not move them
                  lvItem.Remove()
            Next lvItem
      End If
End Sub
As shown in the code above, the ItemDrag event is raised from the ListView control as soon as the user starts to drag the ListView node. The DoDragDrop method initiates the drag-and-drop procedure with the selected ListView items.
The DragEnter event occurs when the ListViewNode object is dragged from the ListView to the TreeView control. In this event, we check the validity of the drag operation by verifying that the data being dragged is the collection of selected items in the ListView control.
Finally the DragDrop event occurs when the ListViewNode object is dropped at the destination point of the TreeView control. The drop point is calculated and the ListViewNode objects (that are to be added to the destination node) are retrieved by looping into the SelectedListViewItemCollection. That is all the code required for the drag-drop operation.
Step 5: I have added this last step basically to let you know about a handy event related to the drag-drop operation: the GiveFeedback event. The GiveFeedback event occurs during a drag-drag operation and lets the source of the drag event to change the appearance of the mouse pointer over a valid target. This step provides the user with a different visual during a drag-and-drop operation. So that means if you have your own cursor file, you can easily display it to the users during the drag operation using this event.
A sample of how to use this event is shown below:
C#
private void listView1_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
    e.UseDefaultCursors = false;
    if ((e.Effect & DragDropEffects.Move) == DragDropEffects.Move)
        Cursor.Current = Cursors.Cross;
    else
        Cursor.Current = Cursors.Default ;
}
VB.NET
Private Sub listView1_GiveFeedback(ByVal sender As Object, ByVal e As GiveFeedbackEventArgs)
      e.UseDefaultCursors = False
      If (e.Effect And DragDropEffects.Move) = DragDropEffects.Move Then
            Cursor.Current = Cursors.Cross
      Else
            Cursor.Current = Cursors.Default
      End If
End Sub
Just like this, you can create your own cursor file and display that to the users.
In this article, we explored how to drag and drop multiple items from a ListView control to a TreeView control. We also explored how to change the default cursor during a drag drop operation. I hope this article was useful and I thank you for viewing it.
If you liked the article,  Subscribe to my RSS Feed.
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 Ehsan on Friday, October 3, 2008 3:36 PM
Your articles could really use some screen-shots and/or live demos.
Comment posted by Suprotim Agarwal on Friday, October 3, 2008 11:14 PM
Ehsan: Sure.
Comment posted by pooja soni on Tuesday, June 18, 2013 6:23 AM
thx for this code but i want my code for aspx  web controls.
this code is can be useful but my requirement is for aspx web controls
Comment posted by Bharathiraja on Saturday, January 18, 2014 7:33 AM
HI, your code is really use full to me, Thank you soo much
Comment posted by lallous on Wednesday, April 16, 2014 10:27 PM
good write up. keep it up.

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