ProblemYou have two ListBox controls on a form, and you want the user to be able to drag and drop items between the lists. SolutionSample code folder: Chapter 14\DragDropLists Use code similar to that found in Recipe 14.14 in conjunction with the ListBox control's DoDragDrop() method to enable dragging and dropping between ListBoxes. DiscussionCreate a new Windows Forms application, and add two ListBox controls named ListBox1 and ListBox2 to the form. In both controls, set the AllowDrop property to TRue, and set the SelectionMode property to MultiExtended. In the properties for ListBox1, select the Items property, and click the "…" button in its data value area. In the String Collection Editor window that appears, enter multiple lines of text, separating them by pressing the Enter key. (We entered the words "One" through "Six.") Figure 14-13 shows this process in action. Figure 14-13. Using the ListBox's String Collection EditorClose the String Collection Editor; you should have a form that looks like Figure 14-14. Figure 14-14. Two listboxes with draggable itemsNow add the following code to the form: Private dragBounds As Rectangle Private dragMethod As String Private Sub ListBox1_DragEnter(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles ListBox1.DragEnter ' ----- Yes, we accept the items. If (e.Data.GetDataPresent(ListBox2.SelectedItems. _ GetType( )) = True) Then _ e.Effect = DragDropEffects.Move End Sub Private Sub ListBox1_DragDrop(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles ListBox1.DragDrop ' ----- Accept the dropped items. For Each oneItem As Object In _ e.Data.GetData(ListBox2.SelectedItems.GetType( )) ListBox1.Items.Add(oneItem) Next oneItem End Sub Private Sub ListBox1_MouseDown(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles ListBox1.MouseDown, ListBox2.MouseDown ' ----- Prepare the draggable content. If (CType(sender, ListBox).SelectedItems.Count = 0) _ Then Return ' ----- Don't start the drag yet. Wait until we move a ' certain amount. dragBounds = New Rectangle(New Point(e.X - _ (SystemInformation.DragSize.Width / 2), _ e.Y - (SystemInformation.DragSize.Height / 2)), _ SystemInformation.DragSize) If (sender Is ListBox1) Then dragMethod = "1to2" Else dragMethod = "2to1" End If End Sub Private Sub ListBox1_MouseMove(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles ListBox1.MouseMove ' ----- Ignore if not dragging from ListBox1. If (dragMethod <> "1to2") Then Return ' ----- Have we left the drag boundary? If (dragBounds.Contains(e.X, e.Y) = False) Then ' ----- Start the drag-and-drop operation. If (ListBox1.DoDragDrop(ListBox1.SelectedItems, _ DragDropEffects.Move) = _ DragDropEffects.Move) Then ' ----- Successful move. Remove the items from ' this list. Do While ListBox1.SelectedItems.Count > 0 ListBox1.Items.Remove(ListBox1.SelectedItems(0)) Loop End If dragMethod = "" End If End Sub Private Sub ListBox1_MouseUp(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles ListBox1.MouseUp, ListBox2.MouseUp ' ----- End of drag-and-drop. dragMethod = "" End Sub Private Sub ListBox2_DragEnter(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles ListBox2.DragEnter ' ----- Yes, we accept the items. If (e.Data.GetDataPresent(ListBox1.SelectedItems. _ GetType( )) = True) Then _ e.Effect = DragDropEffects.Move End Sub Private Sub ListBox2_DragDrop(ByVal sender As Object, _ ByVal e As System.Windows.Forms.DragEventArgs) _ Handles ListBox2.DragDrop ' ----- Accept the dropped items. For Each oneItem As Object In _ e.Data.GetData(ListBox1.SelectedItems.GetType( )) ListBox2.Items.Add(oneItem) Next oneItem End Sub Private Sub ListBox2_MouseMove(ByVal sender As Object, _ ByVal e As System.Windows.Forms.MouseEventArgs) _ Handles ListBox2.MouseMove ' ----- Ignore if not dragging from ListBox2. If (dragMethod <> "2to1") Then Return ' ----- Have we left the drag boundary? If (dragBounds.Contains(e.X, e.Y) = False) Then ' ----- Start the drag-and-drop operation. If (ListBox2.DoDragDrop(ListBox2.SelectedItems, _ DragDropEffects.Move) = _ DragDropEffects.Move) Then ' ----- Successful move. Remove the items from ' this list. Do While ListBox2.SelectedItems.Count > 0 ListBox2.Items.Remove(ListBox2.SelectedItems(0)) Loop End If dragMethod = "" End If End Sub If you look closely at this code, you will find that much of it is replicated. To support two-way dragging, all code that applies to ListBox1 appears again for ListBox2. Run this program, and then drag items from one listBox to the other. You can also multiselect and move multiple items at once. Many controls support the DoDragDrop() method. It accepts data content to send and a set of allowed send methods: If (SomeControl.DoDragDrop(dataContent, _ DragDropEffects.Move) = DragDropEffects.Move) Then ' ----- Successful move. End If Calling this function is easy, and it can be done at any time. Most of the code in this sample deals with determining what content can be sent and when. The DragDropEffects enumeration, used for the second DoDragDrop() argument, indicates which operations the supplier of the data is permitting with the supplied content. Its Move, Copy, and Link enumeration members can be joined with a bitwise Or to indicate multiple allowed features: ' ----- Allow copy and move. Select Case SomeControl.DoDragDrop(dataContent, _ DragDropEffects.Move Or DragDropEffect.Copy) Case DragDropEffects.None ' ----- The target did not accept the content. Case DragDropEffects.Copy ' ----- The target copied the content. Case DragDropEffects.Move ' ----- The target moved the content. End Select See AlsoRecipe 14.14 shows you how to accept dragged-and-dropped files in a ListBox. |