WPF Drag Drop - When Does DragLeave Fire?
I am getting DragLeave Events when dragging from a parent to child control. I would only expect to get this event when moving outside the bounds of a control. How can I implement this?
Please refer to this simple sample application.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<TextBox Height="50" >Hilight and Drag this text</TextBox>
<Border BorderBrush="Blue" BorderThickness="2">
<StackPanel AllowDrop="True" Name="Stack" >
<Label >If I drag text across the gray line, Stack.DragLeave will fire.</Label>
<Separator></Separator>
<Label>I only expect to get this event when leaving the blue rectangle. </Label>
</StackPanel>
</Border>
<TextBlock >Stack.DragLeave Count: <Label x:Name="countLabel" /></TextBlock>
</StackPanel>
</Window>
and in the code behind
C开发者_JAVA百科lass MainWindow
Private Sub Stack_DragLeave(ByVal sender As Object, ByVal e As System.Windows.DragEventArgs) Handles Stack.PreviewDragLeave
countLabel.Content = countLabel.Content + 1
End Sub
End Class
I've recently been working on my own application that is using WPF drag/drop extensively and after spending half a day (debugging, googling, re-reading documentation) on exactly same issue you are seeing, I could only conclude there's a "future enhancement" buried somewhere in WPF library.
It appears there's a quirk in the drag/drop system. While the user is dragging the object over our control it appears the system will quite frequently send us
DragLeave
events, followed immediately byDragEnter
events. So when we getDragLeave
, we can't be sure that the drag/drop operation was actually terminated. Therefore, instead of doing cleanup immediately, we schedule the cleanup to execute later and if during that time we receive anotherDragEnter
orDragOver
event, then we don't do the cleanup.
This was my solution:
protected virtual void OnTargetDragLeave(object sender, DragEventArgs e)
{
_dragInProgress = false;
_target.Dispatcher.BeginInvoke( new Action( ()=>
{
if( _dragInProgress == false ) OnRealTargetDragLeave( sender, e );
} ) );
}
protected virtual void OnTargetDragOver(object sender, DragEventArgs e)
{
_dragInProgress = true;
OnQueryDragDataValid( sender, e );
}
精彩评论