【问题标题】:WPF's command firing twice on fast doubleclickWPF的命令在快速双击时触发两次
【发布时间】:2017-07-30 18:03:02
【问题描述】:

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

现在,在每个命令上,应用程序都被全屏旋转动画覆盖,从而阻止了与应用程序的任何进一步交互。

This github repo 包含该问题的简约再现。请注意:

  • 当 Button 的命令触发时,“IsBusy”标志设置为 true
  • 因此,将显示 BusyIndi​​cator 叠加层
  • 因此,直到 300 毫秒后才能再次按下按钮

但是,特别是在速度较慢的计算机上,当快速双击时(真的很快,就像游戏一样快),可以在 BusyIndi​​cator 阻止第二次调用的情况下触发两次命令(如果输出显示2 条“点击”线接二连三)。

这对我来说是出乎意料的行为,因为 IsBusy 标志在 UI 线程上立即设置为 true。 第二次点击怎么能通过? 我希望 IsBusy Binding 在 UI 线程上显示覆盖,阻止任何进一步的交互?

github 示例还包含 2 个解决方法:

  1. 使用 ICommand.CanExecute 阻止 Execute 处理程序
  2. 使用 PreviewMouseDown 防止双击

我正在尝试了解问题所在。 您更喜欢哪种解决方法?

【问题讨论】:

    标签: wpf


    【解决方案1】:

    诊断

    这只是我的猜测,并不是一个可靠和确认的信息,但似乎当您单击鼠标按钮时,命中测试会立即完成,但所有与鼠标相关的事件都只是计划引发(使用Dispatcher 我想)。重要的是,被点击的控件是在点击发生时确定的,而不是在上一次点击被完全处理之后(包括所有可能发生的 UI 更改)。

    因此,在您的情况下,即使第一次单击导致显示 BusyIndicator 覆盖(并因此阻止)Button,如果您设法在实际显示 BusyIndicator 之前第二次单击(并且这不会立即发生),将计划引发Button 上的点击事件(这将在显示BusyIndicator 之后发生),即使此时BusyIndicator 也会再次执行命令可能会阻止Button

    解决方案

    如果您的目标是在前一个命令仍在执行时阻止命令执行,那么显而易见的选择是使Command.CanExecute 结果取决于IsBusy 标志的状态。此外,我什至不会将其称为解决方法,而是适当的设计

    您在这里所面临的是一个明确的示例,说明了为什么您不应该让您的业务逻辑依赖于 UI。首先,因为渲染很大程度上依赖于机器的处理能力,其次因为到目前为止用另一个控件覆盖一个按钮并不能保证该按钮不能被“点击”(例如使用UI Automation框架)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      • 2019-06-09
      • 2016-12-12
      • 1970-01-01
      • 2014-01-17
      • 2021-07-08
      • 1970-01-01
      相关资源
      最近更新 更多