PreviewMouseLeftButtonDown 事件偶尔会在触摸控件外部时触发

Posted

技术标签:

【中文标题】PreviewMouseLeftButtonDown 事件偶尔会在触摸控件外部时触发【英文标题】:PreviewMouseLeftButtonDown event occasionally fires when touching outside the control 【发布时间】:2021-12-26 07:38:18 【问题描述】:

我有一个带有PreviewMouseLeftButtonDown 事件处理程序的 WPF 文本框,在带有触摸屏的笔记本电脑上运行。

当我触摸 TextBox 时,事件处理程序会按预期触发。但是,如果我随后触摸应用程序中的其他位置,该事件将在 8 或 9 次触摸后触发。即使触摸不在 TextBox 控件的顶部,.NET 似乎也认为控件已被直接触摸。据我所知,事件处理程序的发送者和鼠标事件参数在合法的 TextBox 触摸和控件外的第 9 次触摸之间没有显示出任何可识别的区别。

这可以很容易地在一个独立的应用程序中重现(参见下面的代码和步骤):

    触摸文本框一次。应该会打开一个新窗口以显示触发的事件。 关闭由事件处理程序创建的窗口 在应用程序窗口中任何非文本框的地方触摸 9 次。 应该会再次打开一个窗口,这意味着事件已触发。
public MainWindow()

    InitializeComponent();            
    MyTextBox.PreviewMouseLeftButtonDown += MyTextBox_PreviewMouseLeftButtonDown;


private void MyTextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)

    var win = new Window();
    win.ShowDialog();

是否有任何解释为什么在 .NET 中触摸控件外部有时会触发控件的鼠标事件? 是否有解决此问题的方法,以便在不触发误报事件的情况下同时支持触摸和鼠标?

【问题讨论】:

【参考方案1】:

经过多次搜索找到解决方案。

这是一个已知错误(请参阅https://github.com/dotnet/wpf/issues/2491)。

解决方法是在事件处理程序的Dispatcher.BeginInvoke() 调用中执行ShowDialog() 代码。

可能发生的事情背后的理论是,在事件处理程序期间将焦点更改为新窗口会导致控件继续认为它处于“触地”状态。当进行后续触摸时,WPF 认为它是多点触摸操作的“第二根手指”并创建另一个处理程序。它这样做直到所有“十根手指”都被按下。之后,它循环回到第一个处理程序。由于控件仍然认为它被触摸,所以当您的“第一根手指”触摸应用程序上的任何位置时它会触发。

这解释了为什么在文本框外触摸 9 次后事件始终触发,以及为什么在事件处理程序完成后调用 ShowDialog 可以解决问题。

【讨论】:

以上是关于PreviewMouseLeftButtonDown 事件偶尔会在触摸控件外部时触发的主要内容,如果未能解决你的问题,请参考以下文章