开发者

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

WPF Drag Drop - When Does DragLeave Fire?


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 by DragEnter events. So when we get DragLeave, 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 another DragEnter or DragOver 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 );
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜