2017-07-29 205 views
1

从生产应用程序中,我们注意到我们的WPF按钮通过快速双击触发ICommand.Execute方法两次。WPF的命令在快速双击上触发两次

现在,在每个命令中,应用程序都会覆盖全屏幕微调器动画,从而阻止与应用程序的进一步交互。

This github回购包含问题的简约回购。需要注意的是:

  • 时,按钮的命令触发时,“IsBusy”标志被设置为true
  • 作为结果,BusyIndi​​cator控件覆盖将显示
  • 作为结果,该按钮不能再压直到后300毫秒

然而,特别是在较慢的计算机上,当快速双击(真快,如游戏,快即是),可两次开火命令没有BusyIndi​​cator控件阻止第二个电话(这可以如果输出在o之后显示2个“点击”行,可以看到另一个)。

这对我来说是意想不到的行为,因为IsBusy标志立即在UI线程上设置为true。 第二次点击能够通过吗? 我会希望IsBusy绑定显示UI线程上的覆盖,阻止任何进一步的交互?

GitHub的样品还包括2个解决方法:

  1. 使用ICommand.CanExecute阻止使用PreviewMouseDown防止双击

我想了解执行处理

  • 问题是什么。 你更喜欢什么样的解决方法?

  • 回答

    1

    诊断

    这只是我的猜测,而不是固体,并确认信息,但似乎当您单击鼠标按钮,命中测试立即完成,但所有的鼠标相关的事件仅安排被提出(使用Dispatcher我想)。重要的是,单击的控件在点击发生时确定,而不是在完成前一次点击(包括可能遵循的所有UI更改)后才确定。

    所以你的情况,即使实际显示在显示BusyIndicator覆盖(从而阻塞)的Button,如果你设法单击该BusyIndicator前的第二次先点击结果(这不会立即发生),则Button上的点击事件将被调度(将在BusyIndicator显示之后发生),导致命令被再次执行,即使此时BusyIndicator可能会阻止Button

    解决方案

    如果你的目标是防止,而前一个仍在执行的不二之选命令执行,使Command.CanExecute结果取决于IsBusy标志的状态。此外,我甚至不称之为解决方法,而是正确的设计

    你在这里面临的是一个明确的例子,你为什么不应该让你的业务逻辑依赖于UI。首先,因为渲染很大程度上取决于机器的处理能力,其次因为远程覆盖按钮并不能保证按钮不能被“点击”(例如使用UI Automation框架)。