c# - 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 事件处理程序甚至没有按下鼠标左键触发;只有鼠标右键吗?
解决方案
这与路由事件有关。与普通事件不同,路由事件可以标记为已处理,之后将不再调用该事件的处理程序。
MouseDown
并且MouseMove
正在冒泡路由事件,这意味着它们从最深的元素(按钮内的元素)开始,然后通过它们的父级“冒泡”向上,朝向Window
. 任何父级都可以为这些事件注册一个处理程序,并且当事件达到该父级的级别时将调用它。但是,如果任何子级将事件标记为已处理,则该事件将永远不会到达父级,并且永远不会调用父级的处理程序。
这就是这里发生的事情。Button
有一个MouseDown
内部处理程序。当Button
确定它已被单击时,它会引发自己的Click
事件并将标记MouseDown
为已处理。Button
似乎也可以处理MouseMove
,但仅在单击正在进行时。这就是为什么在左键单击期间不会调用事件处理程序的原因,因为左键单击会触发“单击”,最终会在这些事件脱离Button
.
PreviewMouseDown
和PreviewMouseMove
另一方面,它们都是隧道路由事件,这意味着它们从最广泛的父级 (the Window
) 开始,并朝着光标的确切点向内工作。隧道事件发生在冒泡事件之前;鼠标输入首先进入光标,然后冒泡。
如果将事件处理程序附加到PreviewMouseDown
andPreviewMouseMove
而不是MouseDown
and MouseMove
,您将看到您期望的所有鼠标输入。
有趣的旁注:你实际上可以在你身上玩同样的Button
把戏Button
。如果你PreviewMouseDown
在它进入之前标记为已处理Button
,那么它永远不会引发它的Click
事件。
推荐阅读
- amazon-web-services - 无法创建预签名 URL 以从 eu-west-3 下载对象
- c - 创建代码以打印 3 个数字之间的最大值的问题
- sql - 如何从 SQL Server 删除 CSV 导出中填充的双引号
- python - 无法在 Django 中引用相关的多对多对象
- html - 浏览器密码管理器可以只记住用户名吗?
- sql-server - 更新 SQL Server 中具有列名的所有表中的值
- git - Git LFS 文件未推送到远程仓库
- microsoft-graph-api - Delta 查询不适用于某些租户
- angular - 基于firebase实时数据库问题中的另一个属性查询子节点
- ruby-on-rails - 生成动态实例变量