Reputation: 6982
I am working on a WPF application which shows a list of files stored on a remote server (just like dropbox). I want users to drag and drop them onto desktop or any folder. There are many questions posted related to this but none of them really give a complete solution.
Here is the complete code I am using https://github.com/dotriz/VirtualDragDrop/
This is a very simple task if file is stored on local system, but here file is on a remote server and need to be downloaded first.
The only article related to this, is 13 years old posted here https://dlaa.me/blog/post/9923072. It has few issues too, like
Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC)
Here is the code used on MouseDown event of a label. It uses VirtualFileDataObject class from the link given above
private void VirtualFile2_MouseButtonDown(object sender, MouseButtonEventArgs e)
{
var virtualFileDataObject = new VirtualFileDataObject();
virtualFileDataObject.SetData(new VirtualFileDataObject.FileDescriptor[]
{
new VirtualFileDataObject.FileDescriptor
{
Name = "test.zip",
ChangeTimeUtc = DateTime.Now.AddDays(-1),
StreamContents = stream =>
{
using(var webClient = new WebClient())
{
var data = webClient.DownloadData("https://somesite.com/test.zip");
stream.Write(data, 0, data.Length);
}
}
},
});
DoDragDropOrClipboardSetDataObject(e.ChangedButton, VirtualFile2, virtualFileDataObject, DragDropEffects.Copy);
}
private static void DoDragDropOrClipboardSetDataObject(MouseButton button, DependencyObject dragSource, VirtualFileDataObject virtualFileDataObject, DragDropEffects allowedEffects)
{
try
{
VirtualFileDataObject.DoDragDrop(dragSource, virtualFileDataObject, allowedEffects);
}
catch (COMException)
{
// Failure; no way to recover
}
}
Upvotes: 7
Views: 768
Reputation: 138950
I can successfully use the provided reproduction program. It works at least on Windows 10, 11, x86 x64 in Release and Debug configuration, when ran without debugging it.
DV_E_FORMATETC (0x80040064 ) is just a standard error code that means the data object doesn't support the clipboard format that's requested. This error is common in copy/paste, drag&drop and clipboard operations.
What doesn't work at all is:
void System.Runtime.InteropServices.ComTypes.IDataObject.GetData(ref FORMATETC format, out STGMEDIUM medium)
while running in Debug mode.I don't think you can debug a .NET program (with today tools) with breakpoints or exceptions being throw when in a DoDragDrop function call.
DoDragDrop
is a big modal loop that eats most messages sent to a window. Unfortunately the .NET debugger facility or exception handler (in clr.dll) seems to also wait on this loop for some reason. So, hitting a breakpoint or handling an exception creates a hang in the program itself (and in the debugger too) that you can only break the dead lock by killing the debugged process the hard way (taskkill /im myprocess.exe /f
command line for example).
So my recommendation is to:
avoid putting breakpoints in these portions of code
wrap these functions in try/catch
block and use some non-intrusive trace mechanism, something like this:
void System.Runtime.InteropServices.ComTypes.IDataObject.GetData(ref FORMATETC format, out STGMEDIUM medium)
{
try
{
....
}
catch(Exception ex)
{
Trace.WriteLine("GetData Error: " + ex);
throw; // rethrow as is
}
}
Upvotes: 1
Reputation: 2530
EDIT: This answer is wrong
I can explain why the UI hangs and how to solve it. There are two IO operations inside VirtualFile2_MouseButtonDown which you perform in a blocking way. This obviously blocks the UI thread until both operations finish.
private async void VirtualFile2_MouseButtonDown
This way, VirtualFile2_MouseButtonDown will return on the first IO operation and continuation tasks will be scheduled on the UI thread when the async IO operation is ready.
Upvotes: 0