首页 > 解决方案 > WPF 左键单击并拖动

问题描述

我一直在尝试使用鼠标事件处理程序。使用 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 事件处理程序甚至没有按下鼠标左键触发;只有鼠标右键吗?

标签: c#wpf

解决方案


这与路由事件有关。与普通事件不同,路由事件可以标记为已处理,之后将不再调用该事件的处理程序。

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

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

PreviewMouseDownPreviewMouseMove另一方面,它们都是隧道路由事件,这意味着它们从最广泛的父级 (the Window) 开始,并朝着光标的确切点向内工作。隧道事件发生冒泡事件之前;鼠标输入首先进入光标,然后冒泡。

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

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


推荐阅读