Drag & Drop between Listview in detail mode and Windows Explorer

S

Stephan Steiner

Hi

Basically I'm trying to do something as in this CodeProject article:
http://www.codeproject.com/csharp/Explorer_Drag_Drop.asp
With the exeption that my Listview has to act like Windows Explorer
(within some boundaries.. in the end the goal is to have something
akin to your average FTP client with one window showing local and one
remote content).

I have pretty much all the explorer functionality down (copy/cut/paste/
delete/properties, navigation and whatnot). I can also drag and drop
files from my Listview to windows explorer (both copy and move), and
even dropping files dragged from Windows Explorer works - sort of. My
issue is with the ListView's InsertionMark - it remains set to the
first item visible in the ListView (so its index being 0) at all
times, so no matter where I let go of the mouse button, items are
dropped onto the first item currently visible in the ListView.

Here's a snippet of my code

private void fileBrowser_ItemDrag(object sender, ItemDragEventArgs e)
{
ListView lv = (ListView)sender;
string[] files = getSelectedFilesArray(lv);
if (files.Length > 0)
{
DoDragDrop(new DataObject(DataFormats.FileDrop,
files), DragDropEffects.Copy | DragDropEffects.Move);
}
}

This ought to be correct since dragging and dropping out of my app
works just fine.

And here's a working copy of the DragOver event handler:

private void fileBrowser_DragOver(object sender, DragEventArgs e)
{
// we need some filedrop data - otherwise indicate that
dropping won't work
if (!e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.None;
return;
}
if ((e.KeyState & SHIFT) == SHIFT && (e.AllowedEffect &
DragDropEffects.Move) == DragDropEffects.Move)
e.Effect = DragDropEffects.Move;
else if ((e.KeyState & CTRL) == CTRL && (e.AllowedEffect &
DragDropEffects.Copy) == DragDropEffects.Copy)
e.Effect = DragDropEffects.Copy;
else if ((e.AllowedEffect & DragDropEffects.Move) ==
DragDropEffects.Move) // default action = move
{
e.Effect = DragDropEffects.Move;
// here we could check if we're moving the file to
another drive and change to copy if so
}
else
e.Effect = DragDropEffects.None;
Point targetPoint = this.fileBrowser.PointToClient(new
Point(e.X, e.Y));
int targetIndex =
fileBrowser.InsertionMark.NearestIndex(targetPoint);
targetIndex = this.fileBrowser.InsertionMark.Index;
localFileSizeLabel.Text = "drop target : " + targetIndex +
" mouse X: " + e.X + " mouse Y: " + e.Y;
}

Since the InsertionMark is never changed from 0, targetIndex remains
-1 at all times (even though I see the mouse moving when I'm dumping
out the mouse position). And as my ListView is in detail mode,
ListView.FindNearestItem won't work to yield the item currently under
the mouse cursor.

Since I also need a proper InsertionMark for the DragDrop event (and
I'm not getting it), it explains why my files always end up in either
the currently visible directory, or if the first item is a folder, in
that folder.

How do I get the InsertionMark to cooperate?

Regards
Stephan
 
S

Stephan Steiner

As usual I couldn't let it go and found the solution.

In case somebody runs into the same issue, here's where I went wrong:

Forget about the InsertionMark - it looks like this is for moving
things horizontally. What I need lies in the vertical axis. In fact I
almost had it - I've tried getting the ListViewItem the mouse hovers
over via ListView.GetItemAt() - my mistake was using the X and Y
coordinates from ItemDragEventArgs given to the DragOver event,
instead of first converthing those global coordinates to coordinates
within the control I'm interested in as follows:

Point targetPoint = ListView.PointToClient(new Point(e.X, e.Y));

Once I started using the coordinates from targetPoint for the
GetItemAt method, I finally go back the item I was looking for.

Regards
Stephan
 

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