7

私はWPFを学習しようとしているので、ここに簡単な質問があります。

Stretchユーザー設定可能なプロパティを持つ別のデータオブジェクトにバインドされたImage要素を含むウィンドウがあります

<Image Name="imageCtrl" Source="{Binding MyImage}" Stretch="{Binding ImageStretch}" />

ユーザーが画像の上にマウスを移動したときに、元の画像に対するマウスの座標を決定し(コントロールに表示されるときに発生するストレッチ/トリミングの前に)、それらの座標で何かを実行したいと思います(画像を更新します)。

Imageコントロールを介してMouseMoveイベントにイベントハンドラーを追加できることは知っていますが、座標を変換する最善の方法がわかりません。

void imageCtrl_MouseMove(object sender, MouseEventArgs e)
{
    Point locationInControl = e.GetPosition(imageCtrl);
    Point locationInImage = ???
    updateImage(locationInImage);
}

Sourceこれで、のサイズをコントロールのサイズと比較してからActualSize、スイッチをオンにimageCtrl.StretchしてXとYのスカラーとオフセットを計算し、自分で変換を実行できることがわかりました。しかし、WPFにはすでにすべての情報があり、これはWPFライブラリのどこかに組み込まれている可能性のある機能のようです。だから私は疑問に思っています:短くて甘い解決策はありますか?それとも私はこれを自分で書く必要がありますか?


編集私は私の現在の、それほど短くて甘い解決策を追加しています。それほど悪くはありませんが、WPFがこの機能を自動的に提供しなかった場合は、多少驚きます。

Point ImgControlCoordsToPixelCoords(Point locInCtrl, 
    double imgCtrlActualWidth, double imgCtrlActualHeight)
{
    if (ImageStretch == Stretch.None)
        return locInCtrl;

    Size renderSize = new Size(imgCtrlActualWidth, imgCtrlActualHeight);
    Size sourceSize = bitmap.Size;

    double xZoom = renderSize.Width / sourceSize.Width;
    double yZoom = renderSize.Height / sourceSize.Height;

    if (ImageStretch == Stretch.Fill)
        return new Point(locInCtrl.X / xZoom, locInCtrl.Y / yZoom);

    double zoom;
    if (ImageStretch == Stretch.Uniform)
        zoom = Math.Min(xZoom, yZoom);
    else // (imageCtrl.Stretch == Stretch.UniformToFill)
        zoom = Math.Max(xZoom, yZoom);

    return new Point(locInCtrl.X / zoom, locInCtrl.Y / zoom);
}
4

1 に答える 1

8

ViewBox を使用すると、おそらく簡単になります。例えば:

<Viewbox Stretch="{Binding ImageStretch}">
    <Image Name="imageCtrl" Source="{Binding MyImage}" Stretch="None"/>
</Viewbox>

次に、GetPosition(..) を呼び出すと、WPF は自動的にスケーリングを考慮します。

void imageCtrl_MouseMove(object sender, MouseEventArgs e) 
{ 
    Point locationInControl = e.GetPosition(imageCtrl);
}
于 2010-04-04T06:09:30.650 に答える