2016-11-11 28 views
0

我有一個列表框,其中子項是擴展器。我需要爲此實現DragDrop事件。如果我在XAML中編寫WPF:帶有擴展器的ListBoxItem無法展開後添加PreviewMouseLeftButtonDown事件處理程序到父列表框

<ListBox PreviewMouseLeftButtonDown="StartDragDrop"> 

,StartDragDrop方法工作正常,但子擴展器無法展開。 如果我寫

<ListBox MouseLeftButtonDown="StartDragDrop"> 

,孩子擴展是正確的作品,但StartDragDrop方法不工作。 我認爲問題與泡沫和隧道事件有關,但我不知道明確的解決方案。 我需要兩個,StartDragDrop方法和ListBox子擴展器Expand方法,都是正確的。我該怎麼辦?

+0

你可以發佈你的XAML模式嗎?我想,這還不足以思考解決方案。 –

回答

0

的主要思想是調用的DoDragDrop在PreviewMouseMove()事件,馬託當移動偏移大於不知何故值大。

1)這裏列表框中:

<ListBox AllowDrop="True" Drop=" ListBox_Drop" PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown" PreviewMouseMove="ListBox_PreviewMouseMove"> 

ListBoxItems是擴展器,如果我們實現DragAndDrop不能擴大。

2)現在,我們必須添加2個變量(我用VB.NET):

Private isDragging As Boolean = False 'flag: is drag operation in process?' 
Private dragStartPoint As Point 'coords of dragging start.' 

3)記得預覽點擊鼠標起點座標:

Private Sub ListBox_PreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs) 
    dragStartPoint = e.GetPosition(Me) 
End Sub 

4)在PreviewMouseMove得到將起點移動到當前的移動點偏移量。如果偏移大於某個值,我們啓動DragAndDrop操作並設置標誌isDragging來記住這一點。

Private Sub ListBox_PreviewMouseMove(sender As System.Object, e As MouseEventArgs) 
    If e.LeftButton = MouseButtonState.Pressed Then 
     Dim diff As Vector = Point.Subtract(dragStartPoint, e.GetPosition(Me)) 
        If (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance) OrElse (Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance) Then 
      If Not isDragging Then 
             isDragging = True 'the flag is active until drop event raises.' 
                Dim lstBox As ListBox = TryCast(sender, ListBox) 'get sender ListBox' 
                If lstBox IsNot Nothing Then 
                 Dim data As Object = GetDataFromListBox(lstBox, e.GetPosition(lstBox)) 'get data for drag-and-drop; need to be realized; there are some realizations at Stackoverflow.com presented.' 
Dim effects As DragDropEffects = DragDrop.DoDragDrop(lstBox, data, DragDropEffects.Move) 'initiate drag-and-drop.' 

                 End If 
             End If 
         End If 
     End If 
    End Sub 

5)等待處理拖放操作:

Private Sub ListBox_Drop(sender As Object, e As DragEventArgs) 
     isDragging = False 'reset isDragging flag.' 
        Dim lstBox As ListBox = TryCast(sender, ListBox) 'get sender ListBox.' 
        If lstBox IsNot Nothing Then 
         Dim myObj As MyClass = TryCast(e.Data.GetData(GetType(MyClass)), MyClass) 
     '...some actions' 
        End If 
End Sub 

我已經意識到這個想法,它的工作原理完全我的需求:

  • 上MouseLeftButtonClick ListBoxItems與擴展器膨脹和 崩潰,
  • 在MouseMove上按下左鍵DragAndDrop操作是 作品, ListBoxItems能夠被排序。
0

你完全正確地認爲,它必須做一些隧道和冒泡的事情。在冒泡(無預覽)事件之前執行外部控件的隧道(帶預覽)事件。但它並不妨礙後者被執行。這僅適用於整個事件鏈e.Handled中某處設置爲true的情況。看到這個例子:

XAML:

<Border Background="Red" PreviewMouseMove="OnPreviewMouseMove"> 
    <Border Background="Blue" MouseMove="OnMouseMove" /> 
</Border> 

C#

private void OnPreviewMouseMove(object sender, MouseEventArgs e) 
{ 
    Debug.WriteLine("Preview outer"); 
    e.Handled = true; // this prevents OnMouseMove from being executed 
} 

private void OnMouseMove(object sender, MouseEventArgs e) 
{ 
    Debug.WriteLine("NoPreview inner"); 
} 

如果刪除行 「e.Handled = TRUE;」,的OnMouseMove將受到打擊。如果你自己沒有設置這個,請考慮一下,調用base。「event-name」可能會這樣做。

希望它有幫助。

的Jürgen

+0

謝謝。我會在星期一檢查並通知結果。 – Aave

+0

當我點擊我的listviewitem後,DoDragDrop事件上升。我可以通過拖放來移動列表項目。但是expander.expand事件仍然沒有上升。 – Aave

+0

好的,我解決了這個問題。主要思想是:1)通過PreviewMouseLeftButton得到移動的初始點,2)在光標移動偏移量大於MinimumDragDistance之後,如果「isDragging」變量爲假,3)在PreviewMouseMove事件中調用DoDragDrop方法,4)保持isDragging = true,直到掉落。我會很快發佈完整的代碼。 – Aave

相關問題