WPF:带有扩展器的ListBoxItem在将PreviewMouseLeftButtonDown事件处理程序添加到父ListBox后无法展开

时间:2016-11-11 11:53:48

标签: wpf events listbox event-handling listboxitem

我有一个ListBox,其中子项是扩展器。我需要为此实现DragDrop事件。如果我写XAML

<ListBox PreviewMouseLeftButtonDown="StartDragDrop">

,StartDragDrop方法效果很好,但子扩展器无法扩展。 如果我写

<ListBox MouseLeftButtonDown="StartDragDrop">

,子扩展器的工作正确,但StartDragDrop方法不起作用。 我认为问题与泡沫和隧道事件有关,但我不知道明确的解决方案。 我需要两个,StartDragDrop方法和ListBox子扩展器Expand方法,都是正确的。我该怎么办?

2 个答案:

答案 0 :(得分: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”可能会这样做。

答案 1 :(得分:0)

主要思想是在PreviewMouseMove()事件中调用DoDragDrop mathod,当移动偏移量大于某种方式值时。

1)这里是列表框:

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

ListBoxItems是Expanders,如果我们实现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上获取移动起点到当前移动点偏移。如果offset大于某个值,我们启动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

我已经意识到这个想法,而且它确实是我的需要:

  • on MouseLeftButtonClick ListBoxItems with Expanders是扩展和 崩溃,
  • 在MouseMove上按下左键DragAndDrop操作是 有效,ListBoxItems可以进行排序。