2011-10-28 43 views
1

我想寫一些通用代碼來處理WPF放置目標中的滴。 AllowDrop設置爲true,並且我已經連接到DragEnter,DragOver,DragLeave,&拖放放置目標UIElement。使用冒泡事件可以放置放置目標。放置目標如何在WPF中檢測到已取消的拖放操作?

注意我無法訪問拖動源 - 這是應用程序間拖動&拖放。

如果我有一些UI清理要在可能的下降結束時執行,並且用戶按下Esc來取消下降,那麼放下目標似乎永遠不會得到一個特定事件,我可以與其他所有事件區分開來。下降很容易 - 但是什麼表明取消?

我的問題是這樣的:

  • DragLeave爲冒泡路由事件。
  • e.OriginalSource始終通過測試設置爲此事件(和相應的預覽)。
  • 目標是一個ItemsControl(Listbox是我目前正在測試的)。

當我拖動我的預期拖放目標時,我從目標中的子視覺效果中獲取了大量DragLeave事件。 我從來沒有從目標本身得到任何東西。網格,矩形,邊框,文本塊,他們都很高興地向我發送DragLeave,但沒有一個來自我連接的實際ItemsControl。我認爲這可能是一個棘手的問題,但我已經將ItemsControl的背景設置爲一種顏色,並沒有什麼區別。

我錯過了什麼?我該如何確定下降操作已經完成?

(我試圖解決的實際問題是,我在TreeView中實現了一些自定義拖動行爲,當您將鼠標懸停在它們上方時展開文件夾,並取消定時器&撤消展開,更多的來,但我甚至不能讓事件爲ListBox打火)。

+0

有一個相關的問題在http://stackoverflow.com/questions/5447301/wpf-drag-drop-when-does-dragleave-fire;我希望有更好的解決方案。 – naviwhack

回答

0

在這裏你確實有一個複雜的場景,所以這將從基本開始,希望能給你一個方向並希望有一個解決方案。

如果控件標記爲AllowDrop = true,框架將只會通知DragEnter事件。所以確保你已經做到了。這聽起來像你,但我只是想確定。

我不知道爲什麼你需要DragLeave事件,但如果它是抓住選定的數據,獲取數據的最簡單方法是不掛鉤到DragLeave中,而是掛接到PreviewMouseMove中。然後,您可以確定是否按下鼠標,並在確定DoDragDrop之前移動多少距離。

在這種情況下,您還可以添加和分析拖動數據。當拖動開始,你可以創建一個新的數據對象,並與的DoDragDrop調用發送:

private static void listBox_PreviewMouseMove(object sender, MouseEventArgs e) 
    { 
    // Get the current mouse position 
    var mousePos = e.GetPosition(null); 
    var diff = startPoint - mousePos; 

    if (canScroll && e.LeftButton == MouseButtonState.Pressed && 
     (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || 
      Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)) 
    { 
     var dataObject = (from lbi in startList.Items.Cast<object>().Select((t, i) => (ListBoxItem)startList.ItemContainerGenerator.ContainerFromIndex(i)) where lbi != null && lbi.IsSelected select Convert.ToString(lbi.Content)).ToList(); 

     // Initialize the drag & drop operation 
     var listBoxData = new ListBoxData(){ StartList = startList, Data = dataObject}; 
     var dragData = new DataObject("listBoxData", listBoxData); 

     System.Windows.DragDrop.DoDragDrop(startList, dragData, DragDropEffects.Move); 
    } 
    } 

這拖拽數據是通過DragEventArgs目的是通過使用(如果不重命名事件參數現在訪問,它的電子商務):

e.Data.GetData("listBoxData") 

我的建議是添加一些獨特的信息拖動事件數據來區分基於數據的事件。您可以選擇列表框中的數據項目,也可以選擇保存數據項目的新類別以及其他指標。

+0

不幸的是,這個假設我是編寫DoDragDrop部分的人。我只能影響接收放置的代碼。如果我可以把代碼放在DoDragDrop被調用的地方,我會知道返回值的結果(例如用戶按下Esc,它會是None),但不幸的是,那些代碼位於另一個應用程序:) – naviwhack

+0

在你的DragOver事件處理程序中,你是否試圖查看它是否有任何數據? – Josh

+0

是 - DragOver事件檢查傳入格式並相應地設置效果。這是在效果被設置爲非無的情況下,因爲它是所需的放下,即放開鼠標按鈕會產生放置事件。如果發生丟棄,我可以從Drop事件清理我的UI; Esc的取消是令我困惑的一點。 – naviwhack

0

支票e.Source,而不是e.OriginalSource,如果你已經設置的DropTarget =上的ItemsControl &「真」您有連接到ItemsControl的DropOver事件,事件參數e.Source應該是ItemsControl的。

+0

這不回答問題。問題在於檢測在拖放TARGET中是否取消了拖放操作。你的答案是關於如何在消息源中啓動取消。 QueryContinueDrag事件永遠不會在放置目標中引發。 –