入力ヒットテストでは、RenderTransform
プロパティに大きなスケーリングファクタを持つPath要素で不正な結果が返されます。変換されたパスでヒットテストが正しく行われない
次のXAMLは、円で塗りつぶされたパスとHand
カーソルを定義しています。下の画像に見られるよう
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<EllipseGeometry RadiusX=".5" RadiusY=".5" Center="1,1"/>
</Path.Data>
<Path.RenderTransform>
<ScaleTransform ScaleX="150" ScaleY="150"/>
</Path.RenderTransform>
</Path>
</Canvas>
その位置が形状外の方法であるが、Hand
カーソルが表示されます。大きなパスと小さいスケーリング
は期待通りに問題が消え、カーソルの動作要因。キャンバス上のマウスイベントハンドラでこの
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var canvas = (UIElement)sender;
var hitElement = canvas.InputHitTest(e.GetPosition(canvas));
Trace.TraceInformation("hitElement = {0}", hitElement);
}
のような明示的なヒットテストを実行
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="100,100"/>
</Path.Data>
<Path.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</Path.RenderTransform>
</Path>
</Canvas>
は、同じ間違った結果を提供します。スケーリングされたパスの外側にマウスをクリックすると、パスがヒットエレメントとして返されます。
この問題はSilverlightには表示されません。
ここで問題となるのは、この動作の原因と回避方法です。 Path要素の元のサイズを単純に変更することはできないため、「大規模要素を使用しない」などの回答は役に立ちません。
現状の回避策は、RenderTransformでパスを変換するのではなく、(変換をGeometry.Transform
プロパティに適用することによって)代わりにデータを変換することです。しかし、複雑な塗りつぶし(たとえば、ImageBrush)があるので、塗りつぶしブラシも変換する必要があります(変換を設定するだけでなく、ビューポートも設定する必要があります)。
また、実際の変換はスケーリングだけでなく、回転して平行移動するMatrixTransformです。
この問題は、他のジオメトリと追加の変換でも発生することに注意してください。たとえば、RectangleGeometryを使用して変形されたPathは、同様に正しくない動作を示します。
大規模な因子と誤:小さなスケールファクタで正しい
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<RectangleGeometry Rect=".5,.5,1,1"/>
</Path.Data>
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="150" ScaleY="150"/>
<RotateTransform Angle="45" CenterX="150" CenterY="150"/>
<TranslateTransform X="100"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Canvas>
:
<Canvas Background="LightGray">
<Path StrokeThickness="0" Fill="Blue" Cursor="Hand">
<Path.Data>
<RectangleGeometry Rect="50,50,100,100"/>
</Path.Data>
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
<RotateTransform Angle="45" CenterX="150" CenterY="150"/>
<TranslateTransform X="100"/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Canvas>
ソリューション:*大規模な因子を使用していません*。ナー、冗談だよ。 'RenderTranform'を' LayoutTransform'に変更すると起こりますか? –
既にLayoutTransformはオプションではありませんが、これを試しました。とにかく、それはLayoutTransformでも同じように動作します。 – Clemens
'Path。[Render | Layout] Transform'の代わりに' RectangleGeometry.Transform'を使うことを考えましたか?あなたは、ジオメトリ自体へのアクセス権を持っているので、あなたはすでに変換されたジオメトリをレンダリングするためにあなたの形状を有することができ、その後、ヒットテストをより自然にする必要があります。 – heltonbiker