从生产应用程序中,我们注意到我们的WPF按钮在快速双击时触发ICommand.Execute方法两次。
现在,在每个Command上,应用程序都覆盖了全屏微调器动画,阻止了与应用程序的任何进一步交互。
This github repo包含对该问题的简约重复。请注意:
然而,特别是在慢速计算机上,当快速双击(真的很快,就像快速游戏那样)时,可以在没有BusyIndicator阻止第二次调用的情况下触发命令两次(如果输出显示,则可以看到2'紧跟'彼此之后的行'。
这对我来说是意想不到的行为,因为在UI线程上IsBusy标志立即设置为true。 为什么第二次点击能够通过? 我希望IsBusy Binding在UI线程上显示叠加,阻止任何进一步的交互?
github示例还包含2个解决方法:
我正在努力了解问题所在。 您更喜欢哪种解决方法?
答案 0 :(得分:1)
这只是我的猜测,而不是一个可靠且确认的信息,但似乎当您单击鼠标按钮时,即时完成命中测试,但所有与鼠标相关的事件仅计划被提升(使用我认为Dispatcher
。重要的是,单击的控件是在单击发生时确定的,而不是在完全处理上一次单击之后(包括可能跟随的所有UI更改)。
因此,在您的情况下,即使第一次点击导致显示BusyIndicator
覆盖(并因此阻止)Button
,如果您设法在{{1}之前第二次点击实际显示(并且不会立即发生),BusyIndicator
上的click事件将被调度(将在Button
显示后发生),导致命令被执行即使在那时BusyIndicator
可能会阻止BusyIndicator
。
如果您的目标是阻止命令执行,而前一个命令仍在执行,那么显而易见的选择是使Button
结果取决于Command.CanExecute
标志的状态。此外,我甚至不称之为解决方法,而是正确的设计。
您在这里面对的是一个明确的例子,说明为什么您不应该让您的业务逻辑依赖于UI。首先,因为渲染在很大程度上取决于机器的处理能力,其次因为到目前为止用另一个控件覆盖按钮并不能保证按钮不能被“点击”(例如使用UI Automation框架)。