rickb Posted January 9, 2010 Posted January 9, 2010 I need to be able to move listbox items around a collection of up to 12 listboxes. For example, I move an item from listbox1 to listbox2; later, I need to move that same item from listbox2 to listbox3, and then on a future date move the item from listbox3 back to listbox1. I also need the item to be removed from its previous location when it moves to a new listbox. Here is the code I have for moving items between 2 listboxes: Private Sub listbox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown If ListBox1.SelectedIndex < 0 Then Return ListBox1.DoDragDrop(ListBox1.Items(ListBox1.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) End Sub Private Sub listbox2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox2.MouseDown If ListBox2.SelectedIndex < 0 Then Return ListBox2.DoDragDrop(ListBox2.Items(ListBox2.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) End Sub Private Sub listbox2_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragEnter e.Effect = DragDropEffects.All End Sub Private Sub listbox1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter e.Effect = DragDropEffects.All End Sub Private Sub listbox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop If ListBox2.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) = -1 Then ListBox2.Items.Add(e.Data.GetData(DataFormats.Text).ToString) ListBox1.Items.Remove(ListBox1.Items(ListBox1.SelectedIndex)) End If End Sub Private Sub listbox1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop If ListBox1.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) = -1 Then ListBox1.Items.Add(e.Data.GetData(DataFormats.Text).ToString) ListBox2.Items.Remove(ListBox2.Items(ListBox2.SelectedIndex)) End If End Sub This is not original code from me; I got it from another site. I modified this code to include a third listbox, but the modification doesn't remove the item from the its previous listbox (I added the listbox3 "Remove" code to the original DragDrop events and duplicated the MouseDown and DragEnter events); it copies it to the new listbox. I appreciate any help or guidance. Quote
Leaders snarfblam Posted January 9, 2010 Leaders Posted January 9, 2010 You should probably post the actual code you are using so it is easier to see where the problem is. I don't see any references to ListBox3 in what you've got there. Quote [sIGPIC]e[/sIGPIC]
rickb Posted January 9, 2010 Author Posted January 9, 2010 Sorry about that. I solved the lesser problem of doing more than 2 listboxes (it works with 3 listboxes), so I'll post that code. However, this doesn't resolve the larger issue where I need to be able to swap items between 12 listboxes because this code would get ridiculously long. Here is the code: Private Sub listbox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown If ListBox1.SelectedIndex < 0 Then Return ListBox1.DoDragDrop(ListBox1.Items(ListBox1.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) End Sub Private Sub listbox2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox2.MouseDown If ListBox2.SelectedIndex < 0 Then Return ListBox2.DoDragDrop(ListBox2.Items(ListBox2.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) End Sub Private Sub listbox3_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox3.MouseDown If ListBox3.SelectedIndex < 0 Then Return ListBox3.DoDragDrop(ListBox3.Items(ListBox3.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) End Sub 'These subs allow entrance into the selected listbox Private Sub listbox2_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragEnter e.Effect = DragDropEffects.All End Sub Private Sub listbox1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter e.Effect = DragDropEffects.All End Sub Private Sub listbox3_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox3.DragEnter e.Effect = DragDropEffects.All End Sub 'These subs allows the cursor to enter the listboxes and drop items into them Private Sub listbox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop If ListBox2.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) = -1 Then ListBox2.Items.Add(e.Data.GetData(DataFormats.Text).ToString) If ListBox1.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) <> -1 Then ListBox1.Items.Remove(ListBox1.Items(ListBox1.SelectedIndex)) Else ListBox3.Items.Remove(ListBox3.Items(ListBox3.SelectedIndex)) End If End If End Sub Private Sub listbox1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop If ListBox1.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) = -1 Then ListBox1.Items.Add(e.Data.GetData(DataFormats.Text).ToString) If ListBox2.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) <> -1 Then ListBox2.Items.Remove(ListBox2.Items(ListBox2.SelectedIndex)) Else ListBox3.Items.Remove(ListBox3.Items(ListBox3.SelectedIndex)) End If End If End Sub Private Sub listbox3_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox3.DragDrop If ListBox3.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) = -1 Then ListBox3.Items.Add(e.Data.GetData(DataFormats.Text).ToString) If ListBox1.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) <> -1 Then ListBox1.Items.Remove(ListBox1.Items(ListBox1.SelectedIndex)) Else ListBox2.Items.Remove(ListBox2.Items(ListBox2.SelectedIndex)) End If End If End Sub I would like to be able to work through the different listboxes with a SELECT CASE statement by referencing each lisbox, but I'm not sure how I would do that. Thanks for any help or guidance. Quote
Leaders snarfblam Posted January 10, 2010 Leaders Posted January 10, 2010 (edited) When the drag operation starts, you can store a reference to the control that started the operation. That way you don't have to go looking for it later on. Private Sub listbox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown If ListBox1.SelectedIndex < 0 Then Return ListBox1.DoDragDrop(ListBox1.Items(ListBox1.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) End Sub becomes... [color="Blue"]Dim dragSource As ListBox[/color] Private Sub listbox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown If ListBox1.SelectedIndex < 0 Then Return ListBox1.DoDragDrop(ListBox1.Items(ListBox1.SelectedIndex).ToString, DragDropEffects.Copy Or DragDropEffects.Move) [color="Green"]'Remember what control the data came from.[/color] [color="Blue"]dragSource = ListBox1[/color] End Sub But why not generalize it a bit more? [color="Blue"]Dim dragSource As ListBox[/color] Private Sub listbox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown [color="Blue"]TryBeginDrag(ListBox1)[/color] End Sub [color="Green"]'We can use this sub for any ListBox we want to drag data from[/color] [color="Blue"]Private Sub TryBeginDrag(source As ListBox) If source.SelectedIndex >= 0 Then source.DoDragDrop(source.SelectedItem.ToString, DragDropEffects.Copy Or DragDropEffects.Move) dragSource = source End If End Sub[/color] Now when we drag and drop to another control, we already know exactly where to remove the string from. Private Sub listbox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop If ListBox2.FindStringExact(e.Data.GetData(DataFormats.Text).ToString) = -1 Then ListBox2.Items.Add(e.Data.GetData(DataFormats.Text).ToString) [color="Blue"] dragSource.Items.Remove(dragSource.SelectedItem)[/color] End If End Sub Again, we can generalize: Private Sub listbox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop [color="Blue"] TryDrop(ListBox2, e.Data)[/color] End Sub [color="Blue"] Private Sub TryDrop(destination As ListBox, data As IDataObject) [color="Green"] 'I find it easier to read my code if I evaluate a large expression outside 'the if statement and give it a name.[/color] Dim destContainsData As Boolean = destination.FindStringExact(data.GetData(DataFormats.Text).ToString()) <> -1 If Not destContainsData Then destination.Items.Add(Data.GetData(DataFormats.Text).ToString) dragSource.Items.Remove(dragSource.SelectedItem) End If End Sub [/color] I haven't tested this code and my VB is a bit rusty, but at the very least you should get the idea. Hope it helps. Edited January 10, 2010 by snarfblam Quote [sIGPIC]e[/sIGPIC]
rickb Posted January 10, 2010 Author Posted January 10, 2010 Thanks for the help, marble-eater. I'm getting an error in the TryDrop sub. The code is below and the error is at the arrow: Private Sub TryDrop(ByVal destination As ListBox, ByVal data As IDataObject) Dim destContainsData As Boolean = destination.FindStringExact(data.GetData(DataFormats.Text).ToString()) <> -1 If Not destContainsData Then --> [b]destination.Items.Add(e.Data.GetData(DataFormats.Text).ToString)[/b] dragSource.Items.Remove(dragSource.SelectedItem) End If End Sub Here is the error msg: "Name 'e' is not declared." I tried copying "ByVal e As System.Windows.Forms.DragEventArgs" into the sub declaration, but I got this error msg: "Argument not specified." I also tried to put "ByVal e As System.Windows.Forms.MouseEventArgs", but I got the "Not a member" error msg. I even took the 'e' out; that eliminated the error msg, but the program still did not work properly. Out of curiosity, I answered "Yes" once when asked if I wanted to continue in spite of the error. The program seems to work AFTER the first time I move one item from one listbox to another, but only with the items that have not been moved yet. In case you are wondering, I copied your examples and modified it to work for all the listboxes. Here is the entire code with your modifications: 'We can use this sub for any ListBox we want to drag data from Private Sub TryBeginDrag(ByVal source As ListBox) If source.SelectedIndex > 0 Then source.DoDragDrop(source.SelectedItem.ToString, DragDropEffects.Copy Or DragDropEffects.Move) dragsource = source End If End Sub Private Sub TryDrop(ByVal destination As ListBox, ByVal data As IDataObject) 'I find it easier to read my code if I evaluate a large expression outside 'the if statement and give it a name. Dim destContainsData As Boolean = destination.FindStringExact(data.GetData(DataFormats.Text).ToString()) <> -1 If Not destContainsData Then --> destination.Items.Add(e.Data.GetData(DataFormats.Text).ToString) dragsource.Items.Remove(dragsource.SelectedItem) End If End Sub '=============================================================================================================================================== '=============================================================================================================================================== Private Sub listbox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseDown TryBeginDrag(ListBox1) End Sub Private Sub listbox2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox2.MouseDown TryBeginDrag(ListBox2) End Sub Private Sub listbox3_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox3.MouseDown TryBeginDrag(ListBox3) End Sub Private Sub listbox1_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragDrop TryDrop(ListBox1, e.Data) End Sub Private Sub listbox2_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragDrop TryDrop(ListBox2, e.Data) End Sub Private Sub listbox3_DragDrop(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox3.DragDrop TryDrop(ListBox3, e.Data) End Sub Private Sub listbox1_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox1.DragEnter e.Effect = DragDropEffects.All End Sub Private Sub listbox2_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox2.DragEnter e.Effect = DragDropEffects.All End Sub Private Sub listbox3_DragEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles ListBox3.DragEnter e.Effect = DragDropEffects.All End Sub Thanks again for any help you can give me. Quote
Leaders snarfblam Posted January 10, 2010 Leaders Posted January 10, 2010 My mistake. destination.Items.Add([color="Red"]e.[/color]Data.GetData(DataFormats.Text).ToString) [/Code] Should be [Code] destination.Items.Add(Data.GetData(DataFormats.Text).ToString) [/Code] Quote [sIGPIC]e[/sIGPIC]
rickb Posted January 11, 2010 Author Posted January 11, 2010 Thanks for the reply. I know my last post was a long one, but somewhere in there I mentioned that I already removed the 'e.' The error goes away, but the program doesn't work properly until after the first time I move an object, and then seemingly stops allowing DragEnter events (You can't move anything into the listboxes; it's as if the AllowDrop property was switched to 'False'). I included the error part in the post with the hope that you saw something you missed. I do appreciate the time you've put into this issue; I'm going to play with it a while and see if I can narrow down what the problem is. I would gladly accept anymore ideas/suggestions you have. Thanks again. Quote
Leaders snarfblam Posted January 11, 2010 Leaders Posted January 11, 2010 Sorry, I guess I didn't read it well enough. Here is what seems to be the problem: I didn't realize that the Control.DoDragDrop method blocks the main thread until the drag and drop operation is complete. This is the corrected code for TryBeginDrag: Private Sub TryBeginDrag(ByVal source As ListBox) If source.SelectedIndex >= 0 Then [color="Red"]dragSource = source[/color] [color="Green"]' moved[/color] [color="Green"] ' This method blocks the main thread[/color] source.DoDragDrop(source.SelectedItem.ToString, DragDropEffects.Copy Or DragDropEffects.Move) End If End Sub dragSource needs to be set before calling DoDragDrop. Otherwise it won't get set until after the DragEnter and DragDrop events are raised. I guess I didn't realize that it worked that way because I'm not familiar with DotNet's drag and drop system. I don't use it because it just seems aweful (probably because it just wraps the Windows drag and drop system, which is, presumably, aweful). Quote [sIGPIC]e[/sIGPIC]
rickb Posted January 12, 2010 Author Posted January 12, 2010 Excellent, marble-eater! Thanks for figuring that out. I played around with the code for a couple of hours today, but nothing seemed to work. Thanks again for your effort. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.