【问题标题】:WPF Left click and dragWPF 左键单击并拖动
【发布时间】:2020-07-31 02:01:02
【问题描述】:

我一直在尝试使用鼠标事件处理程序。使用 MouseDown 似乎只适用于鼠标右键。并且 PreviewMouseLeftButton 在我释放左键之前不会激活 MouseMove 事件。

所以这段代码:

    private void NewButton_MouseDown(object sender, MouseButtonEventArgs e)
    {
        var test = e.LeftButton;
        var test2 = e.RightButton;
        if (!bButtonIsDown)
        {
            bButtonIsDown = true;
            Button mover = (Button)sender;
            pntEnterPoint = e.GetPosition(this.cnvsLinkScreen);

            cnvsLinkScreen.MouseMove += CnvsLinkScreen_MouseMove;
            cnvsLinkScreen.MouseUp += CnvsLinkScreen_MouseUp;
            
            spMover = (StackPanel)((Button)sender).Parent;
            pntPreviousPoint.X = Canvas.GetLeft(spMover);
            pntPreviousPoint.Y = Canvas.GetTop(spMover);

        }
    }

    private void NewButton_MouseMove(object sender, MouseEventArgs e)
    {
        Button mover = (Button)sender;
        StackPanel spMover = (StackPanel)((Button)sender).Parent; 
        base.OnMouseMove(e);
        if (e.LeftButton == MouseButtonState.Pressed)
        {

            // Inititate the drag-and-drop operation.
            FindChild<StackPanel>(cnvsLinkScreen, "CSVImport");
            pntEnterPoint = e.GetPosition(this.cnvsLinkScreen);
            Canvas.SetLeft(spMover, pntEnterPoint.X + 1);
            Canvas.SetTop(spMover, pntEnterPoint.Y + 1);
        }
    }

有效,但只有右键。启用事件处理程序时:

newButton.MouseDown += NewButton_MouseDown;

鼠标左键不会触及该事件处理程序,我认为这很奇怪。

我已经阅读了大量内容,人们参考了 PreviewMouseLeftButtonDown 事件处理程序,但是当我在适当的位置使用它(相同的代码)时,cnvsLinkScreen.MouseMove += CnvsLinkScreen_MouseMove 不会触发,直到我放开左边鼠标按钮(按钮向上),然后 StackPanel 拖动,直到我单击并放下它。

我设置了断点并看到事件处理程序正在设置,但是直到释放左按钮后它才起作用。显然,我在这个事件处理程序上遗漏了一些东西。

为什么 MouseDown 事件处理程序甚至没有按下鼠标左键触发;只需按下鼠标右键?

【问题讨论】:

  • 请注意,WPF 内置了对拖放的支持:docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/…
  • 是的,我这样做是为了在画布中获取对象,但是当我尝试这样做以移动它们时,对象不会在画布上滑动,而是鼠标图标发生变化并且对象保持原位,直到我放开鼠标。我想要对象在拖动时移动的动画。

标签: c# wpf


【解决方案1】:

这与Routed Events 有关。与普通事件不同,路由事件可以是marked as handled,之后不会再调用该事件的其他处理程序。

MouseDownMouseMovebubbling routed events,这意味着它们从最深的元素(按钮内的元素)开始,然后通过它们的父元素“冒泡”向上,朝向Window。任何父级都可以为这些事件注册一个处理程序,并且当事件达到该父级的级别时将调用它。但是,如果任何子级将事件标记为已处理,则该事件将永远不会到达父级,并且永远不会调用父级的处理程序。

这就是这里发生的事情。 Button 有一个 MouseDown 的处理程序内部。当Button 确定它已被点击时,它会引发自己的Click 事件并MouseDown 标记为已处理Button 似乎也可以处理 MouseMove,但仅在单击正在进行时。这就是为什么在左键单击期间不会调用事件处理程序的原因,因为左键单击会触发“单击”,最终会在这些事件脱离Button 之前对其进行处理。

另一方面,PreviewMouseDownPreviewMouseMove 都是 tunneling routed events,这意味着它们从最广泛的父级(Window)开始,然后向内移动到光标的确切位置。隧道事件发生在冒泡事件之前;鼠标输入首先向光标移动,然后再向上冒泡。

如果您将事件处理程序附加到 PreviewMouseDownPreviewMouseMove 而不是 MouseDownMouseMove,您将看到所有您期望的鼠标输入。

有趣的旁注:你实际上可以在Button 上玩Button 在你身上玩的同样的把戏。如果在PreviewMouseDown 进入Button 之前将其标记为已处理,那么它将永远不会引发Click 事件。

【讨论】:

  • 我与 PreviewMouseDown 事件具有相同的效果,我单击图像(堆栈面板)并尝试拖动它,但它不会去任何地方。但是当我释放按钮时,它会移动图像,直到我再次单击以释放它。为了确保它不在我的代码中,我取出了 !ButtonDown。在我释放左键之前,MouseMove 事件似乎不会生效...
  • 实际上,我取消了点击哪个鼠标按钮的检查,并且右键仍然有效。但左派没有。所以我注释掉了这一行: if (!bButtonIsDown ) 所以两个鼠标按钮都会触发动作。但同样,右边的按钮按预期工作,左边没有,直到我释放按钮。
  • 啊,明白了!我必须设置 e.handled = true 现在它按预期工作!感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 2013-06-30
  • 2011-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多