UIElementとマウスイベントなどの組み合わせにおける注意
About
WPF で複数の UIElement を自由にレイアウトするようなアプリケーションを作る場合に、特殊な問題が起こる可能性があります。例えばマウスイベントなどが通知されないといった問題です。ここでは Canvas と基本図形を例に問題を説明します。Canvas を使ったレイアウトが最もこの問題を発生すると思われるからです。
1 - Background(Fill)がnullだとマウスイベントが発生しない
UIElement(の一部)はその背景BackgroundないしFillがnullだとマウスイベントが生じないという特性があります。つまりCanvasのBackgroundがnullだったりRectangleのFillがnullである場合には、OnMoveイベントなどは発生しません。透過する背景(Color.Transparent)を設定することでこの問題は回避することができます。
2 - Canvasと基本図形での例
次の図はCanvas上に2つの基本図形を並べています。例えばドラッグアンドドロップでレイアウトを変えるようなアプリケーションだとしましょう。ここで上に重なる図形、図では赤い円のみを選択する場合には、今回取り扱うような問題は発生しません。問題となるのは、図のようにマウスの位置が丁度2つの図形に重なっている場合に、2つの図形をどちらも選択状態にしたいような時です。
この時、例えばMouseLeftButtonDownイベントは図の赤い円(Ellapse)でしか発生しません。ここでWPFにはバブリングやトンネリングという仕組みがあるので、この問題は発生しそうにありませんが、バブリングやトンネリングは親子関係のあるUIElement間にしか発生しません。※バブリングやトンネリングについてはここでは扱いません。
すなわち、Canvas上にある2つの図形はそれぞれ親子関係を持っていませんから、バブリングやトンネリングを起こさない、ということです。ここでもしこの問題を解決するのであれば複数の方法が考えられます。
- Canvas上のUIElementが少ないのであればマウスの座標と要素全てとでHitTestを行う。
- 図形の移動がないなどの場合は、マウスの座標と図形の大きさとで当たりを推定する。
- イベントハンドラはCanvasに設定する。
- 目的によっては実現できないが、複数のレイヤのようにCanvasを扱って切り替える。
- 目的によっては実現できないが、下のUIだけ判定するのであれば上に重なる方のHitTestを無視する。