8

我想在滑块的帮助下调整画布上的圆圈大小。这个圆圈可以通过我在后面的代码中做的一些拖放操作在画布上移动,所以它的位置不是固定的。

我已将滑块的值绑定到椭圆的高度和宽度。不幸的是,当我使用滑块时,圆圈的大小会调整,其左上角(实际上是它所在矩形的左上角)在操作过程中保持不变。

我想调整它的大小,使其中心点在操作过程中保持不变。在 XAML 中是否有一种简单的方法可以做到这一点?顺便说一句,我已经尝试过 ScaleTransform,但它并没有达到我想要的效果。

非常感谢!:-)

<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 绑定到您的高度和宽度。

具体来说(编辑):
为 Canvas.Left 和 Canvas.Top 分别创建一个属性并绑定到这些属性。
存储 Width 和 Heigth 的旧值或旧的滑块值。
每当滑块发生变化时,通过减去存储的值来获得增量变化“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,因此元素的位置就是位置。如果你想改变顶部,左侧的位置,你需要自己做。如果您使用其他面板类型,如网格,则可以更改椭圆的对齐方式,以将其放置在相同的相对位置,无论大小如何。您可以通过在 AdornerDecorator 中添加 Grid 并使 Ellipse 居中来获得该效果,但您还需要将 AdornerDecorator 或 Grid 设置为固定大小,因为它们不会在 Canvas 中拉伸。

您可以使用的最佳解决方案是将 ScaleTransform 应用于 RenderTransform 属性,其 RenderTransformOrigin 为 0.5,0.5。你说你有 ScaleTransform 的问题,但不是问题所在。

于 2010-08-06T12:56:08.153 回答
1

将椭圆包裹在最大尺寸的网格中。只要它更小,Ellipse 就会在 Grid 中居中:

    <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>

您可能需要调整拖动逻辑以处理拖动 Grid 而不是 Ellipse 本身。

于 2010-08-06T13:20:07.957 回答
0

我发现了一种在普通 XAML 中执行此操作的非常简单的方法: set Margin="-1000000"。在此处阅读更多内容:在 WPF 中仅使用 XAML 将元素定位在画布的中心(而不是左上角)

于 2012-11-04T14:40:40.503 回答