WPF:调整圆的大小,保持圆心而不是左上角?

WPF:调整圆的大小,保持圆心而不是左上角?,wpf,xaml,2d,resize,centering,Wpf,Xaml,2d,Resize,Centering,我想用滑块调整画布上的一个圆的大小。这个圆可以通过我在code behind中做的一些拖放操作在画布上移动,所以它的位置不是固定的 我已经将滑块的值绑定到椭圆的高度和宽度。不幸的是,当我使用滑块时,圆的左上角点(实际上是它所在矩形的左上角点)在操作过程中保持不变,从而调整了大小 我想调整它的大小,使其中心点在操作过程中保持不变。在XAML中有没有一种简单的方法可以做到这一点?顺便说一句,我已经试过ScaleTransform,但它并没有达到我想要的效果 非常感谢!:-) 一月 您可以通过Valu

我想用滑块调整画布上的一个圆的大小。这个圆可以通过我在code behind中做的一些拖放操作在画布上移动,所以它的位置不是固定的

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

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

非常感谢!:-)

一月


您可以通过ValueConverter将Canvas.Left和Canvas.Top绑定到您的高度和宽度

具体(编辑):
为Canvas.Left和Canvas.Top分别创建一个属性并绑定到它们。
存储宽度和高度的旧值或旧滑块值。
无论何时更改滑块,通过减去存储值来获得增量更改“dx”。
(不要忘记更新存储值…
将dx添加到宽度和高度属性。
正如威尔所说,将dx/2*-1添加到Canvas.Left和Canvas.Top属性中


这有意义吗?

问题是您正在使用滑块调整宽度和高度。不计算RenderTransferorMorigin周围的宽度和高度;只有RenderTransforms使用该值

下面是一个更正的版本(brb,kaxaml):


当然,这可能不适合你。为什么?我使用的缩放变换不仅缩放圆,还缩放边框;随着圆圈变大,边界也会变大。希望你不会在意这个

另外,在组合变换时(在本例中是缩放然后旋转),要意识到它们是按顺序应用的,并且一个变换可能会影响另一个变换的执行方式。在你的情况下,你不会注意到这一点。但是,如果你在做旋转和平移,顺序是相关的


啊,我在想什么?只需将椭圆粘贴在网格中(最简单的解决方案,但其他容器也可以)。调整椭圆大小时,栅格会自动将椭圆居中。不需要任何值转换器!代码如下:

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

因为您使用的是画布,所以元素的位置就是位置。如果你想改变左上方的位置,你需要自己做。如果使用的是另一种面板类型(如栅格),则可以更改椭圆的对齐方式,以将其放置在相同的相对位置,而不管其大小如何。您可以通过在AdorneDecorator内添加网格并将椭圆居中来获得这种效果,但您还需要将AdorneDecorator或网格设置为固定大小,因为它们不会在画布中拉伸


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

用最大尺寸的网格将椭圆包裹起来。只要较小,椭圆将在栅格中居中:

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


您可能需要调整拖动逻辑来处理网格而不是椭圆本身的拖动

我发现了一种在普通XAML中实现这一点的非常简单的方法:set
Margin=“-1000000”
。请在此处阅读更多内容:

谢谢您的回答!这表明我的问题不完整;-)圆圈在画布上的位置不是固定的,这就是为什么我没有找到使用ValueConverter的方法…等等,这会起作用的。你必须有一个值转换器,它可以
value/2*-1
Hi-Martin!谢谢-我将在周三测试这一点,并报告:)嗨,伙计们!它可以工作-非常感谢你的帮助和耐心:)我不明白这个解决方案,你能一步一步地详细解释吗?ScaleTransform基本上放大了我所有的东西,所以我的装饰条(为了简洁起见,我在代码中省略了)随着我的缩放而变大,笔划厚度(边框大小)也增加了。不过,我只想调整圆本身的大小,笔划厚度和装饰器大小保持不变……因此,从您的回答来看,您似乎想为椭圆设置一个可变的中心点,而不是左上角。通过在AdorneDecorator上添加一个带转换器的绑定到边距,将边距设置为(-ActualWidth/2,-ActualHeight/2,0,0),可以获得这种效果。这将基本上将元素向上和向左移动到您设置为左上方的点的中心。嗨,John!听起来很有趣-感谢您的解决方案:)如果Martin使用Canvas.Top/.Left绑定的解决方案对我不起作用,这可能会非常有用…谢谢!不幸的是,我确实关心边界;-)所以,是的,我已经尝试了ScaleTransform,但这也弄乱了我的装饰器(为了简洁起见,我把它放在这里了)。。。还有其他想法吗?:-)@简:形势很严峻。在这种情况下,您可能需要创建一个自定义控件。原因是无法绑定到Canvas.Left和Canvas.Top。如果可以,可以使用绑定上的转换器获取值(例如滑块值10),求反并将其除以2。这将移动圆的原点以匹配其宽度和高度的增加。由于无法执行此操作,因此可以创建一个自定义控件来执行此计算并更新椭圆曲线
<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>
    <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>