2017-07-29 10 views
1

プロダクションアプリケーションでは、WPFボタンが高速ダブルクリックでICommand.Executeメソッドを2回起動することがわかりました。WPFのコマンドが高速ダブルクリックで2回発生

ここで、すべてのコマンドで、アプリケーションはフルスクリーンのスピナーアニメーションで覆われているため、アプリケーションとのやり取りはこれ以上できません。

This github repoには、問題の最小限の再現が含まれています。なお:ボタンのコマンド火災は、「IsBusy」フラグが結果として

  • trueに設定されている場合

    • 、BusyIndi​​catorオーバーレイは、結果として
    • が表示されます、ボタンをもう一度押すことができません300msの

    後までしかし、特に高速のダブルクリック(つまり、高速にゲームのような、本当に速い)遅いコンピュータ上で、缶(BusyIndi​​catorが2回目の呼び出しをブロックせずにコマンドを2回発射することが可能ですoの直後に2行の 'click'行が表示されている場合に表示されます別のもの)。

    これは予期せぬ動作です.IsBusyフラグはUIスレッド上で真に設定されています。 2回目のクリックはどのように通過できますか? 私は、IsBusy BindingがUIスレッド上にオーバーレイを表示し、それ以上の対話をブロックすることを期待していますか?

    githubのサンプルはまた、2つの回避策含まれています。私は理解しようとしているダブルクリック

  • を防ぐためにPreviewMouseDownを使用して実行し、ハンドラ

  • をブロックするようにICommand.CanExecuteを使用して

    1. を何が問題なの? どのような回避策をお勧めしますか?

  • 答えて

    1

    診断

    これが唯一の私の推測ではなく固体との情報を確認し、あなたがマウスボタンをクリックすると、ヒットテストがすぐに行われますが、すべてのマウス関連のイベントのみが予定されているようです(私は仮定してDispatcherを使用して)提起される。重要なことは、クリックされたコントロールは、クリックが発生した時点で決定され、以前のクリックが完全に処理された後ではないことです(後に続くすべてのUIの変更が含まれます)。

    あなたがBusyIndicator前に、第2回クリックして、管理のであればButtonBusyIndicatorを示す最初のクリックの結果が覆っ(したがって、ブロッキング)しても、あなたのケースで、実際に示されている(そしてそれはすぐに発生しません。 )、Buttonのクリックイベントは発生します(BusyIndicatorが表示された後に発生します)。その時点でBusyIndicatorButtonをブロックしていても、コマンドが再度実行されます。

    あなたの目標は、以前の1はまだ明白な選択を実行している間、コマンドの実行を防ぐためである場合

    ソリューションはCommand.CanExecute結果はIsBusyフラグの状態に依存することです。さらに、私は回避策とも呼ぶことはないが、のという適切なデザインをと呼ぶ。

    あなたがここに直面しているのは、ビジネスロジックがUIに依存しないようにすべき理由の明確な例です。第1に、レンダリングはマシンの処理能力に強く依存し、第2に、別のコントロールでボタンをカバーすることは、ボタンが「クリック」されないことを保証するものではない(例えば、UI Automationフレームワークを使用)。

    関連する問題