2016-11-28 85 views
1

場景:爲UI控件啓用了拖動功能的C#/ WPF應用程序。從Windows資源管理器中拖動文件並將其放到UI控件上時,會出現一個MessageBox。文件拖放事件處理程序中的MessageBox導致Windows資源管理器凍結

問題:只要不點擊MessageBox(通過點擊「OK」),Windows資源管理器被凍結,並且可能等待拖放事件返回。

問:有沒有辦法從其等待發佈Windows資源管理器之前顯示的消息框?那麼「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:有其他類似的問題。然而,沒有辦法「過早地」返回事件。

回答

1

如果我們this documentation article about Drag and Drop operations看看我們可以看到,它說:

當用戶啓動一個拖和拖放操作,源創建一個數據對象,並通過啓動拖環調用DoDragDrop。

所以源窗口現在卡在由DoDragDrop function開始的循環中。

當光標進入另一窗口(被稱爲目標窗口)的DoDragDrop函數將調用目標窗口的IDropTarget接口的DragEnterDragOver方法。

當您釋放鼠標按鈕將數據放到目標窗口時,DoDragDrop函數將調用IDropTarget接口的Drop方法。如果我們再繼續讀書......

當目標已完成使數據對象,它返回下降目標::下降。系統返回源的DoDragDrop調用以通知源數據傳輸已完成。

...我們看到源窗口的DoDragDrop呼叫沒有退出,直到目標窗口已退出其IDropTarget::Drop方法。

在.NET中,當調用IDropTarget::Drop方法時,它將引發DragDrop事件。提高事件意味着它調用所有附加的事件處理程序,並且由於這不是異步的,調用方法(IDropTarget::Drop)將被阻塞,直到所有的DragDrop事件處理程序被調用並退出。

所以回答你的問題:不,你不能「過早地」退回它。它被每線程代碼執行的標準邏輯阻塞:一次一行。

你最好在這裏的選項有:

  1. 啓動任務/您展示的消息框一個新的線程。你可能不得不爲此創建一個消息循環,但我不是100%確定的。

  2. 創建您自己的消息框窗體並使用非模態調用Form.Show()顯示它。

+0

最終MessageBox將被(可能很耗時)的文件加載到內存中。但是,應用程序也應該能夠通過公共的打開文件對話框打開文件。我的sw-architectural-beginner-gut-feeling告訴我(可能不正確),無論文件名/路徑如何出現(拖放或對話框),都應該使用相同的文件加載功能。但是,這裏也許沒有矛盾。也許可以從「國外」任務的開放對話框上下文中調用相同的加載文件函數? – AddeTbkg

+0

@AddeTbkg:是的,一般功能是最好的。是的,該功能可以從OFD和另一個線程/任務中調用。請記住,線程和任務必須調用才能訪問UI。 –