【问题标题】:WPF Drag Drop - When Does DragLeave Fire?WPF 拖放 - DragLeave 何时触发?
【发布时间】:2011-03-27 04:48:09
【问题描述】:

从父控件拖动到子控件时,我收到 DragLeave 事件。我只希望在超出控件范围时获得此事件。我该如何实现?

请参考这个简单的示例应用程序。

<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>

在后面的代码中

Class 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

【问题讨论】:

标签: .net wpf vb.net


【解决方案1】:

我最近一直在开发我自己的应用程序,该应用程序广泛使用 WPF 拖放,在您看到完全相同的问题花了半天(调试、谷歌搜索、重新阅读文档)之后,我只能得出结论隐藏在 WPF 库中某处的“未来增强”。

拖放系统中似乎有一个怪癖。当用户在我们的控件上拖动对象时,系统似乎会经常向我们发送DragLeave 事件,然后立即发送DragEnter 事件。所以当我们得到DragLeave 时,我们不能确定拖放操作是否真的被终止了。因此,我们不是立即进行清理,而是安排稍后执行清理,如果在此期间我们收到另一个 DragEnterDragOver 事件,那么我们不进行清理。

这是我的解决方案:

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 );
}

【讨论】:

  • 感谢 DXM,这似乎解决了绝大多数儿童控件的问题。但是,拖动分隔符控件(可能还有其他控件)会导致调用 OnQueryDragDataValid 方法。
  • @Peter,我在其中添加的对 OnQueryDragDataValid() 的调用用于我的特定实现。如果您不需要它,我认为它不需要在那里。我的设计(我认为 WPF 也希望这样)是 OnQueryDragDataValid() 可以被调用任意次数,您只需要验证放置操作是否有效。
  • @DMX,是的,你是绝对正确的。我的意思是写 OnRealTargetDragLeave 在拖动分隔符控件时触发。我相信这是因为“分隔符控件不会对任何键盘、鼠标、鼠标滚轮或平板电脑输入做出反应,并且无法启用或选择。(来自 MSDN)”。但是,分隔符可以很容易地被其他类似的控件(线、矩形等)替换。再次感谢您的出色解决方案!
  • @DXM 我也为按钮、标签和矩形尝试了这个解决方案,但我的 dragLeave 事件仍然触发。我该怎么办?
  • @DMX。谢谢你,先生!我发现要在 OnDragOver 之前调用 OnDragEnter 方法。所以我还在 OnDragEnter 中添加了_dragInProgress = true。像魅力一样工作!
猜你喜欢
  • 2011-07-28
  • 2020-06-19
  • 2012-08-18
  • 2012-12-21
  • 2012-12-21
  • 1970-01-01
  • 2014-04-27
  • 1970-01-01
  • 2019-06-02
相关资源
最近更新 更多