PreviewMouseLeftButtonDown 事件在控件外部触摸时偶尔会触发
PreviewMouseLeftButtonDown event occasionally fires when touching outside the control
我在带触摸屏的笔记本电脑上有一个带有 PreviewMouseLeftButtonDown
事件处理程序 运行 的 WPF TextBox。
当我触摸 TextBox 时,事件处理程序按预期触发。但是,如果我随后触摸应用程序中的其他地方,该事件将在 8 或 9 次触摸后触发。似乎 .NET 认为控件已被直接触摸,即使触摸不在 TextBox 控件之上。据我所知,事件处理程序的发送者和鼠标事件参数在合法的 TextBox 触摸和控件外的第 9 次触摸之间没有显示任何可识别的差异。
这可以很容易地在独立应用程序中重现(请参阅下面的代码和步骤):
- 触摸一次文本框。应打开一个新的 window 以显示已触发的事件。
- 关闭由事件处理程序
创建的window
- 触摸应用程序中非文本框的任何地方 window 9 次。
- A window 应该再次打开,这意味着事件已触发。
public MainWindow()
{
InitializeComponent();
MyTextBox.PreviewMouseLeftButtonDown += MyTextBox_PreviewMouseLeftButtonDown;
}
private void MyTextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var win = new Window();
win.ShowDialog();
}
- 是否有任何解释为什么控件外部的触摸有时会在 .NET 中触发控件的鼠标事件?
- 是否有针对此问题的解决方法,以便在不误报事件触发器的情况下同时支持触摸和鼠标?
多方查找找到解决方案
这是一个已知错误(参见 https://github.com/dotnet/wpf/issues/2491)。
解决方法是在事件处理程序的 Dispatcher.BeginInvoke()
调用中执行 ShowDialog()
代码。
可能发生的事情背后的理论是,在事件处理程序window 期间将焦点更改为新的 window 会导致控件继续认为它处于“着陆”状态“ 状态。当进行后续触摸时,WPF 认为它是多点触摸操作的“第二根手指”并创建另一个处理程序。它会这样做,直到所有“十根手指”都被按下。之后,它循环回到第一个处理程序。由于控件仍然认为它正在被触摸,因此当您的“第一根手指”触摸到应用程序上的任何位置时,它就会触发。
这解释了为什么在文本框外部触摸 9 次后事件始终触发,以及为什么在事件处理程序完成后调用 ShowDialog 可以解决问题。
我在带触摸屏的笔记本电脑上有一个带有 PreviewMouseLeftButtonDown
事件处理程序 运行 的 WPF TextBox。
当我触摸 TextBox 时,事件处理程序按预期触发。但是,如果我随后触摸应用程序中的其他地方,该事件将在 8 或 9 次触摸后触发。似乎 .NET 认为控件已被直接触摸,即使触摸不在 TextBox 控件之上。据我所知,事件处理程序的发送者和鼠标事件参数在合法的 TextBox 触摸和控件外的第 9 次触摸之间没有显示任何可识别的差异。
这可以很容易地在独立应用程序中重现(请参阅下面的代码和步骤):
- 触摸一次文本框。应打开一个新的 window 以显示已触发的事件。
- 关闭由事件处理程序 创建的window
- 触摸应用程序中非文本框的任何地方 window 9 次。
- A window 应该再次打开,这意味着事件已触发。
public MainWindow()
{
InitializeComponent();
MyTextBox.PreviewMouseLeftButtonDown += MyTextBox_PreviewMouseLeftButtonDown;
}
private void MyTextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var win = new Window();
win.ShowDialog();
}
- 是否有任何解释为什么控件外部的触摸有时会在 .NET 中触发控件的鼠标事件?
- 是否有针对此问题的解决方法,以便在不误报事件触发器的情况下同时支持触摸和鼠标?
多方查找找到解决方案
这是一个已知错误(参见 https://github.com/dotnet/wpf/issues/2491)。
解决方法是在事件处理程序的 Dispatcher.BeginInvoke()
调用中执行 ShowDialog()
代码。
可能发生的事情背后的理论是,在事件处理程序window 期间将焦点更改为新的 window 会导致控件继续认为它处于“着陆”状态“ 状态。当进行后续触摸时,WPF 认为它是多点触摸操作的“第二根手指”并创建另一个处理程序。它会这样做,直到所有“十根手指”都被按下。之后,它循环回到第一个处理程序。由于控件仍然认为它正在被触摸,因此当您的“第一根手指”触摸到应用程序上的任何位置时,它就会触发。
这解释了为什么在文本框外部触摸 9 次后事件始终触发,以及为什么在事件处理程序完成后调用 ShowDialog 可以解决问题。