Ten lines of code to do drag n drop in VB.Net

  • Thread starter James Allen Bressem
  • Start date
J

James Allen Bressem

I was searching through the MSDN documentation trying to figure out how to
do drag n drop and I found a sample program. The sample program did all
sorts of fancy junk like dynamically create it's user controls etc. (pomp -
is it really necessary to be so gaudy when trying to explain a simple
point?) So, realizing the state of the economy and the period of history in
which I was so unfortunately born, I spent the next 3 or so hours weeding
through the affectatious displays of bravado and uselessly flagrant
manefestations of excess (blank lines every where in the sample code - What
does "CONCISE" mean?)

When a people are showing a near complete, generally applicable, state of
chaotic ineptitude something is wrong with the system, through it may look
fine on the outside. Which is why we have UCOM www.UCOM-ISM.com shedding
light on the source of and solution for these obvious yet completely
overlooked social problems.

Anyway; I eventually was able to find the actual code that was necessary to
do drag n drop in VB.NET:

There was 500 lines of code in the sample using a ListBox control!

I was able to do the same thing in a TreeView control with 14 lines of code?
'---------------------------------------------------------------------------
----------------------------------
Protected Sub TreeView1_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles TreeView1.MouseMove
Dim sNodePathStr As String
sNodePathStr = LinkTree.SelectedNode.FullPath()
Dim dropEffect As DragDropEffects = TreeView1.DoDragDrop(sNodePathStr,
DragDropEffects.Copy)
End Sub
Private Sub TreeView1_DragOver(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles TreeView1.DragOver
e.Effect = DragDropEffects.Copy
End Sub
Private Sub TreeView1_DragDrop(ByVal sender As Object, ByVal e As
System.Windows.Forms.DragEventArgs) Handles TreeView1.DragDrop
Dim oDroppedNodePath As Object =
CType(e.Data.GetData(GetType(System.String)), System.Object)
Debug.WriteLine("Selected Item: " & CType(oDroppedNodePath, String))
oNode = LinkTree.GetNodeAt(e.X, e.Y)
Debug.WriteLine("Drop Site: " & oNode.FullPath)
End Class
'---------------------------------------------------------------------------
----------------------------------

-----------------------------
Name: James Allen Bressem
Phone: (323) 691-4279
Email: (e-mail address removed)
UCOM: http://www.ucom-ism.com
Mirror site: http://www.geocities.com/wizardofwizards
-----------------------------
 
F

Fergus Cooney

Hi James,

|| The sample program did all sorts of fancy junk like dynamically create it's
|| user controls etc. (pomp - is it really necessary to be so gaudy when trying
|| to explain a simple point?) So, realizing the state of the economy and the
|| period of history in which I was so unfortunately born, I spent the next 3 or
|| so hours weeding through the affectatious displays of bravado and uselessly
|| flagrant manefestations of excess (blank lines every where in the sample code
|| - What does "CONCISE" mean?)

LOL. Do you mean the example given with Control.DoDragDrop? I agree -
it's horrendous. In my MSDN (2001) it's much, much shorter.

In your example, you start the Drag with MouseMove - this is going to start
a lot of drags. Surely it should be based on the mouse button being held down?
(And there's an assignment to dropEffects but this doesn't then get used.)

Your drag object is a string - the path of the last Node that the mouse moved over.
Would it not be better to drag the Node itself? This will allow better error checking.
That string could have been dragged from anywhere and may not be a Node path at all.

The Drag effect is continually being set in DragOver, but this need only be done once
in DragEnter. It would also be useful to check that the drag contents are the right type
so that the No-drag-here cursor can be displayed for the wrong type.

|| www.UCOM-ISM.com

That's a lot of reading. Probably some good stuff in it.

Regards,
Fergus

<code>
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As EventArgs) Handles MyBase.Load
'Set the AllowDrop property so that data can be dragged onto it.
RichTextBox1.AllowDrop = True

'Add code here to populate ListBox1 with paths to text files.
End Sub

Private Sub ListBox1_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles ListBox1.MouseDown
Dim Lb As ListBox
Dim Index As Integer

'Determine which item was selected.
Lb = sender
Index = Lb.IndexFromPoint (New Point(e.X, e.Y))

'Start a drag-and-drop operation with that item.
If Index >= 0 Then
Lb.DoDragDrop(Lb.Items(Index), DragDropEffects.Link)
End If
End Sub

Private Sub RichTextBox1_DragEnter(ByVal sender As Object, _
ByVal e As DragEventArgs) Handles RichTextBox1.DragEnter
If (e.Data.GetDataPresent("Text")) Then
'Allow copying of the data to the RichTextBox control.
e.Effect = DragDropEffects.Copy
Else
e.Effect = DragDropEffects.None
End If
End Sub

Private Overloads Sub RichTextBox1_DragDrop(ByVal sender As Object, _
ByVal e As DragEventArgs) Handles RichTextBox1.DragDrop
'Load the file into the control.
RichTextBox1.LoadFile(e.Data.GetData("Text"), _
RichTextBoxStreamType.RichText)
End Sub
</code>
 
B

Bernie Yaeger

Hi Fergus,

This raises a real problem for me - how to use drag and drop between 2
listboxes, automatically removing the item selected from frombox and adding
it to tobox. And to complicate it, perhaps a selection of items, either
contiguous or discontiguous. Can you offer any code samples that would put
me in the right direction? Wherever I look on MSDN etc all I find are
examples between a listbox and a textbox or 2 textboxes, but never as I have
described it.

Tx

Bernie Yaeger
 
F

Fergus Cooney

Hi Bernie,

Aaaghhh. I am most frustrated!!! :-((

I've spent the last three hours getting this code ready. It's not hard code.
It should have been a straightforward type-it-and-run. But it wouldn't work!

It seems that I've discovered something amiss with ListBoxes. When doing
drag-n-drop it gets confused about what SelectedIndex, SelectedItems and
the other Selected properties should be.

The multi-select is driving me crazy. For example: SelectedItems.Count
returns 1. But SelectedItems(0) produces an Array bound Exception !!???

The single select works if you only copy but if you try and move an item -
the next move produces an Array bound error - on SelectedIndex - it's not
even an array property!! ???

Anyway, here's the single-selection-only version. Maybe (hopefully) it's
just a bug on my system (Framework 1.0). If you want the multi-selct I can
give it to you and you can see how the method works, and it will look logical
and easy. But it won't work!! ?? (At least not for me)

Good luck

Regards,
Fergus

<code>
Namespace projVB

Class Form_Foo
'Needs two ListBoxes - lstSrc and lstDest.

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim dValues() As Double _
= { 1.23, 23.4, -19.07, 53.456, 0, 499.99 }
Dim dValue As Double
lstSrc.Items.Clear
For Each dValue In dValues
Dim oItem As SomeListItemType
oItem = New SomeListItemType
oItem.Value = dValue
lstSrc.Items.Add (oItem)
Next

lstSrc.SelectionMode = SelectionMode.MultiSimple
lstDest.AllowDrop = True
End Sub

'===========================================================
Private Sub lstSrc_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles lstSrc.MouseDown
If lstSrc.SelectedIndex >= 0 Then
'SelectedIndex gives an array bounds error on
'the second drag. What array??
Dim Index As Integer = lstSrc.SelectedIndex
Console.WriteLine ("DragStart [{0}] - {1}", _
Index, lstSrc.SelectedItem.ToString)
lstSrc.DoDragDrop (lstSrc.SelectedItem, DragDropEffects.Move)
Console.WriteLine ("DragCompleted")
End If
End Sub

'===========================================================
Private Sub lstDest_DragEnter (ByVal sender As Object, _
ByVal e As DragEventArgs) Handles lstDest.DragEnter
Console.WriteLine ("DragEnter - " & e.Effect.ToString)
Debug_WhatDragDataType (e)

If e.Data.GetDataPresent ("projVB.SomeListItemType") Then
Console.WriteLine ("DragEnter - Move allowed")
e.Effect = DragDropEffects.Move
Else
e.Effect = DragDropEffects.None
End If
End Sub

'===========================================================
Private Sub lstDest_DragDrop (ByVal sender As Object, _
ByVal e As DragEventArgs) Handles lstDest.DragDrop
Dim oItem As SomeListItemType = DirectCast _
(e.Data.GetData ("projVB.SomeListItemType"), SomeListItemType)
lstSrc.Items.Remove (oItem) 'The error occurs when this line is used.
lstDest.Items.Add (oItem)
Console.WriteLine ("DragDrop - {0} moved", oItem.ToString)
End Sub

'===========================================================
'Use this to determine what type to
'give to GetDataPresent and GetData
Private Sub Debug_WhatDragDataType (ByVal e As DragEventArgs)
Dim S As String
Dim asF() As String = e.Data.GetFormats
Dim I As Integer
For I = 0 To asF.Length - 1
S = S & asF(I) & vbCrLf
Next
Console.Write ("DragEnter - " & S)
End Sub
End Class

'===========================================================
Class SomeListItemType
Public Value As Double
Public Overrides Function ToString As String
Return Value.ToString ("###.00")
End Function
End Class
</code>
 
B

Bernie Yaeger

Hi Fergus,

Thanks so much for your work on this. I expected there was a bug that was
holding me back, but your code will get me going anyway.

Tx again,

Bernie

Fergus Cooney said:
Hi Bernie,

Aaaghhh. I am most frustrated!!! :-((

I've spent the last three hours getting this code ready. It's not hard code.
It should have been a straightforward type-it-and-run. But it wouldn't work!

It seems that I've discovered something amiss with ListBoxes. When doing
drag-n-drop it gets confused about what SelectedIndex, SelectedItems and
the other Selected properties should be.

The multi-select is driving me crazy. For example: SelectedItems.Count
returns 1. But SelectedItems(0) produces an Array bound Exception !!???

The single select works if you only copy but if you try and move an item -
the next move produces an Array bound error - on SelectedIndex - it's not
even an array property!! ???

Anyway, here's the single-selection-only version. Maybe (hopefully) it's
just a bug on my system (Framework 1.0). If you want the multi-selct I can
give it to you and you can see how the method works, and it will look logical
and easy. But it won't work!! ?? (At least not for me)

Good luck

Regards,
Fergus

<code>
Namespace projVB

Class Form_Foo
'Needs two ListBoxes - lstSrc and lstDest.

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim dValues() As Double _
= { 1.23, 23.4, -19.07, 53.456, 0, 499.99 }
Dim dValue As Double
lstSrc.Items.Clear
For Each dValue In dValues
Dim oItem As SomeListItemType
oItem = New SomeListItemType
oItem.Value = dValue
lstSrc.Items.Add (oItem)
Next

lstSrc.SelectionMode = SelectionMode.MultiSimple
lstDest.AllowDrop = True
End Sub

'===========================================================
Private Sub lstSrc_MouseDown(ByVal sender As Object, _
ByVal e As MouseEventArgs) Handles lstSrc.MouseDown
If lstSrc.SelectedIndex >= 0 Then
'SelectedIndex gives an array bounds error on
'the second drag. What array??
Dim Index As Integer = lstSrc.SelectedIndex
Console.WriteLine ("DragStart [{0}] - {1}", _
Index, lstSrc.SelectedItem.ToString)
lstSrc.DoDragDrop (lstSrc.SelectedItem, DragDropEffects.Move)
Console.WriteLine ("DragCompleted")
End If
End Sub

'===========================================================
Private Sub lstDest_DragEnter (ByVal sender As Object, _
ByVal e As DragEventArgs) Handles lstDest.DragEnter
Console.WriteLine ("DragEnter - " & e.Effect.ToString)
Debug_WhatDragDataType (e)

If e.Data.GetDataPresent ("projVB.SomeListItemType") Then
Console.WriteLine ("DragEnter - Move allowed")
e.Effect = DragDropEffects.Move
Else
e.Effect = DragDropEffects.None
End If
End Sub

'===========================================================
Private Sub lstDest_DragDrop (ByVal sender As Object, _
ByVal e As DragEventArgs) Handles lstDest.DragDrop
Dim oItem As SomeListItemType = DirectCast _
(e.Data.GetData ("projVB.SomeListItemType"), SomeListItemType)
lstSrc.Items.Remove (oItem) 'The error occurs when this line is used.
lstDest.Items.Add (oItem)
Console.WriteLine ("DragDrop - {0} moved", oItem.ToString)
End Sub

'===========================================================
'Use this to determine what type to
'give to GetDataPresent and GetData
Private Sub Debug_WhatDragDataType (ByVal e As DragEventArgs)
Dim S As String
Dim asF() As String = e.Data.GetFormats
Dim I As Integer
For I = 0 To asF.Length - 1
S = S & asF(I) & vbCrLf
Next
Console.Write ("DragEnter - " & S)
End Sub
End Class

'===========================================================
Class SomeListItemType
Public Value As Double
Public Overrides Function ToString As String
Return Value.ToString ("###.00")
End Function
End Class
</code>
 
F

Fergus Cooney

Hi Bernie,

Let me know if you get what I got.
If you do, I'll turn the project into a bug demo.

Oh, and let me know if you want the multi-select version.

Regards,
Fergus
 
B

Bernie Yaeger

Hi Fergus,

Will do - forget the multi - I'm happy enough with the single move drag and
drop.

Regards,

Bernie
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top