【问题标题】:MessageBox in file drag+drop event-handler causes Windows explorer to freeze文件拖放事件处理程序中的 MessageBox 导致 Windows 资源管理器冻结
【发布时间】:2016-11-28 22:55:19
【问题描述】:

场景:为 UI 控件启用拖放的 C#/WPF 应用程序。当从 Windows 资源管理器中拖动文件并将其放在 UI 控件上时,会出现一个 MessageBox。

问题:只要 MessageBox 未被点击(通过点击“确定”),Windows 资源管理器就会被冻结并(可能)等待拖放事件返回。

问题:有什么方法可以让 Windows 资源管理器从等待 MessageBox 显示出来? “DragEventArgs”类的“Handled”属性呢?

代码:

 private void OnDrop_ButtonOpen(object sender, DragEventArgs e)
 {
   if (e.Data.GetDataPresent(DataFormats.FileDrop))
   {
     string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
     MessageBox.Show(files[0]);
   }
 }

PS:还有其他类似的问题。但是,“过早”返回事件没有解决方案。

【问题讨论】:

    标签: c# .net wpf drag-and-drop


    【解决方案1】:

    如果我们看一下this documentation article about Drag and Drop operations,我们可以看到它说:

    当用户开始拖放操作时,源会创建一个数据对象并通过调用 DoDragDrop 启动一个拖动循环

    所以源窗口现在卡在由DoDragDrop function 启动的循环中。

    当光标进入另一个窗口(称为目标窗口)时,DoDragDrop 函数将调用目标窗口的IDropTarget 接口的DragEnterDragOver 方法。 p>

    当您松开鼠标按钮将数据拖放到目标窗口时,DoDragDrop 函数将调用IDropTarget 接口的Drop 方法。如果我们继续阅读......

    当目标完成数据对象时,它从 IDropTarget::Drop 返回。系统返回源的 DoDragDrop 调用以通知源数据传输完成。

    ...我们看到源窗口的DoDragDrop 调用直到目标窗口退出其IDropTarget::Drop 方法后才退出。

    在 .NET 中,当调用 IDropTarget::Drop 方法时,它会引发 DragDrop 事件。引发事件意味着它会调用所有附加的 DragDrop 事件处理程序,并且由于这不是异步的,因此调用方法 (IDropTarget::Drop) 将被阻塞,直到所有 DragDrop 事件处理程序都被调用并退出。

    所以回答你的问题:不,你不能“过早地”退回它。它被每线程代码执行的标准逻辑阻塞:一次一行。

    您最好的选择是:

    1. 在显示消息框的位置启动任务/新线程。您可能需要为此创建一个消息循环,但我不能 100% 确定。

    2. 创建您自己的消息框表单并使用非模态调用Form.Show() 显示它。

    【讨论】:

    • 最终 MessageBox 将被替换为(可能很耗时)将 filedrop 加载到内存中。但是,该应用程序也应该能够通过常见的打开文件对话框打开文件。我的 sw-architectural-beginner-gut-feeling 告诉我(可能是错误的)无论文件名/路径如何遇到(拖放或对话框),都应该使用相同的文件加载功能。不过,这里或许并不矛盾。也许相同的加载文件函数可以从打开对话框上下文从“国外”任务中调用?
    • @AddeTbkg :是的,通用函数是最好的。是的,可以从 OFD 和另一个线程/任务中调用该函数。请记住,线程和任务必须调用才能访问 UI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 2014-12-01
    相关资源
    最近更新 更多