8

スライダーを使用して、キャンバス上の円のサイズを変更したいと思います。この円は、コードビハインドで行ったドラッグアンドドロップ操作でキャンバス上を移動できるため、位置は固定されていません。

スライダーの値を楕円の高さと幅にバインドしました。残念ながら、スライダーを使用すると、操作中に円のサイズが変更され、その左上の点 (実際には、円が置かれている長方形の左上の点) が同じままになります。

操作中に中心点が一定になるようにサイズを変更したいと思います。XAML でこれを行う簡単な方法はありますか? ところで、私はすでに ScaleTransform を試しましたが、私が望んでいたことはうまくいきませんでした。

本当にありがとう!:-)

1月

<Canvas x:Name="MyCanvas">

    <!-- this is needed for some adorner stuff I do in code behind -->
    <AdornerDecorator Canvas.Left="10"
                      Canvas.Top="10">
        <Ellipse x:Name="myEllipse"
             Height="{Binding Path=Value, ElementName=mySlider}"
             Width="{Binding Path=Value, ElementName=mySlider}"
             Stroke="Aquamarine"
             Fill="AliceBlue"
             RenderTransformOrigin="0.5 0.5">
            <Ellipse.RenderTransform>
                <RotateTransform Angle="{Binding Path=Value, ElementName=myRotationSlider}" />
            </Ellipse.RenderTransform>
        </Ellipse>
    </AdornerDecorator>

    <Slider x:Name="mySlider"
            Maximum="100"
            Minimum="0"
            Width="100"
            Value="10"
            Canvas.Left="150"
            Canvas.Top="10" />
    <Slider x:Name="myRotationSlider"
            Maximum="360"
            Minimum="0"
            Width="100"
            Value="0"
            Canvas.Left="150"
            Canvas.Top="50" />
</Canvas>
4

5 に答える 5

4

ValueConverter を介して Canvas.Left と Canvas.Top を Height と Width にバインドできます。

具体的には (編集):
Canvas.Left と Canvas.Top のそれぞれにプロパティを作成し、これらにバインドします。
幅と高さの古い値、または古いスライダーの値を保存します。
スライダーが変更されるたびに、保存された値を差し引いて増分変化「dx」を取得します。
(保存された値を更新することを忘れないでください...)
dx を Width プロパティと Height プロパティに追加します。
そして、Will が言ったように、dx/2*-1 を Canvas.Left および Canvas.Top プロパティに追加します。

それは理にかなっていますか?

于 2010-08-06T12:51:41.487 に答える
2

問題は、SLIDER を使用して幅と高さを調整していることです。RenderTransformOrigin の周りの幅と高さは計算されません。RenderTransforms のみがその値を使用します。

これが修正版です(brb、kaxaml):

<Canvas x:Name="MyCanvas">
<!-- this is needed for some adorner stuff I do in code behind -->
    <AdornerDecorator Canvas.Left="50" Canvas.Top="50">
        <Ellipse
            x:Name="myEllipse"
            Width="10"
            Height="10"
            Fill="AliceBlue"
            RenderTransformOrigin="0.5 0.5"
            Stroke="Aquamarine">
            <Ellipse.RenderTransform>
                <TransformGroup>
                    <RotateTransform Angle="{Binding Path=Value, ElementName=myRotationSlider}"/>
                    <ScaleTransform
                        CenterX=".5"
                        CenterY=".5"
                        ScaleX="{Binding Path=Value, ElementName=mySlider}"
                        ScaleY="{Binding Path=Value, ElementName=mySlider}"/>
                </TransformGroup>
            </Ellipse.RenderTransform>
        </Ellipse>
    </AdornerDecorator>
    <Slider
        x:Name="mySlider"
        Width="100"
        Canvas.Left="150"
        Canvas.Top="10"
        Maximum="10"
        Minimum="0"
        SmallChange=".01"
        Value="1"/>
    <Slider
        x:Name="myRotationSlider"
        Width="100"
        Canvas.Left="150"
        Canvas.Top="50"
        Maximum="360"
        Minimum="0"
        Value="0"/>
</Canvas>

もちろん、これはおそらくうまくいかないでしょう。なんで?さて、私が使用した ScaleTransform は、円だけでなく境界線もズームします。円が大きくなるにつれて、境界線も大きくなります。うまくいけば、あなたはこれを気にしません。

また、変換 (この場合はスケールと回転) を組み合わせるときに、それらが順番に適用されることに注意してください。あなたの場合、これに気付かないでしょう。しかし、たとえば、回転と平行移動を行っている場合は、順序が適切になります。


ああ、私は何を考えていましたか?楕円をグリッドに貼り付けるだけです (最も単純なソリューションですが、他のコンテナーでも機能します)。楕円のサイズが変更されると、グリッドは楕円を自動的に中央に配置します。値コンバーターは必要ありません。コードは次のとおりです。

<Canvas x:Name="MyCanvas">
<!-- this is needed for some adorner stuff I do in code behind -->
    <Grid Width="100" Height="100">
        <AdornerDecorator>
            <Ellipse
                x:Name="myEllipse"
                Width="{Binding Path=Value, ElementName=mySlider}"
                Height="{Binding Path=Value, ElementName=mySlider}"
                Fill="AliceBlue"
                RenderTransformOrigin="0.5 0.5"
                Stroke="Aquamarine">
                <Ellipse.RenderTransform>
                    <RotateTransform Angle="{Binding Path=Value, ElementName=myRotationSlider}"/>
                </Ellipse.RenderTransform>
            </Ellipse>
        </AdornerDecorator>
    </Grid>
    <Slider
        x:Name="mySlider"
        Width="100"
        Canvas.Left="150"
        Canvas.Top="10"
        Maximum="100"
        Minimum="0"
        Value="10"/>
    <Slider
        x:Name="myRotationSlider"
        Width="100"
        Canvas.Left="150"
        Canvas.Top="50"
        Maximum="360"
        Minimum="0"
        Value="0"/>
</Canvas>
于 2010-08-06T12:53:09.180 に答える
2

Canvas を使用しているため、要素の場所は場所です。上、左の位置を変更したい場合は、自分で行う必要があります。Grid などの別の Panel タイプを使用している場合は、Ellipse の配置を変更して、サイズに関係なく同じ相対位置に配置できます。AdornerDecorator 内に Grid を追加して Ellipse を中央に配置することでその効果を得ることができますが、AdornerDecorator または Grid は Canvas 内で引き伸ばされないため、固定サイズに設定する必要もあります。

使用できる最適なソリューションは、RenderTransformOrigin が 0.5,0.5 の RenderTransform プロパティに ScaleTransform を適用することです。あなたは ScaleTransform に問題があると言いましたが、問題の内容はわかりませんでした。

于 2010-08-06T12:56:08.153 に答える
1

Ellipse を最大サイズのグリッドでラップします。小さい限り、楕円はグリッドの中央に配置されます。

    <Grid
        Canvas.Left="10"
        Canvas.Top="10"
        Width="100"
        Height="100">
        <AdornerDecorator>
            <Ellipse x:Name="myEllipse"
             Height="{Binding Path=Value, ElementName=mySlider}"
             Width="{Binding Path=Value, ElementName=mySlider}"
             Stroke="Aquamarine"
             Fill="AliceBlue"
             RenderTransformOrigin="0.5 0.5">
                <Ellipse.RenderTransform>
                    <RotateTransform Angle="{Binding Path=Value, ElementName=myRotationSlider}" />
                </Ellipse.RenderTransform>
            </Ellipse>
        </AdornerDecorator>
    </Grid>

Ellipse 自体ではなく Grid のドラッグを処理するには、ドラッグ ロジックを調整する必要がある場合があります。

于 2010-08-06T13:20:07.957 に答える
0

プレーンな XAML でこれを行うための非常に簡単な方法を見つけました: set Margin="-1000000"。詳細はこちら: WPF で XAML のみを使用して、キャンバス内の要素を (左上隅ではなく) 中央に配置する

于 2012-11-04T14:40:40.503 に答える