我有一个ListBox,其中子项是扩展器。我需要为此实现DragDrop事件。如果我写XAML
<ListBox PreviewMouseLeftButtonDown="StartDragDrop">
,StartDragDrop方法效果很好,但子扩展器无法扩展。 如果我写
<ListBox MouseLeftButtonDown="StartDragDrop">
,子扩展器的工作正确,但StartDragDrop方法不起作用。 我认为问题与泡沫和隧道事件有关,但我不知道明确的解决方案。 我需要两个,StartDragDrop方法和ListBox子扩展器Expand方法,都是正确的。我该怎么办?
答案 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
我已经意识到这个想法,而且它确实是我的需要: