使用WPF中的XAML,通过其中心而不是左上角来定位Canvas中的元素

15
定位一个Canvas元素的常见问题是“如何将元素的中心点定位(而不是左上角)”。

有几种解决方案,但它们都有缺点。

最简单的解决方案是在编程时支持元素大小并设置Canvas.LeftCanvas.Top属性。这个方法有效,但只能使用一次。这个解决方案不支持绑定,在元素大小改变时会出现问题。您还不能使用Canvas.LeftCanvas.Top进行设置。

另一组解决方案涉及使用RenderTransformMargin的翻译变换。这些解决方案需要将某些属性绑定到-0.5 * Width-0.5 * Height。这种绑定需要创建自定义ValueConverter,且无法仅使用XAML创建。

那么,有没有一种简单的方法可以将元素放置在Canvas内,以便其Canvas.LeftCanvas.Top与元素的中心对应,并且还可以将大小和位置属性绑定到其他属性?

4个回答

10

XAML和数据绑定看起来很强大,但有时候简单的问题需要非常复杂的解决方案。在我的绑定库中创建这样的绑定就像写 element.Center = position 或者 element.TopLeft = position - element.Size / 2 那么容易,但不要让我太沉迷其中。

我找到了一个非常简单的解决方案,只使用XAML并支持同时绑定元素的大小和位置属性。似乎当将设置了StretchCenter对齐方式的WPF控件放置在Canvas内时,元素会“凝聚”于以(Canvas.Left, Canvas.Top)点为中心(我们所期望的状态),但会被放置在同一(Canvas.Left, Canvas.Top)点上的“角度板”所阻止。我怎么知道这个“凝聚”呢?当你通过将元素的Margin设置为负值来缓解这个问题时,它就变得明显了。设置负边距允许元素向其中心目标移动。元素移动直到Margin达到(-Height / 2, -Width / 2),使元素完美地居中于(Canvas.Left, Canvas.Top)点。进一步的更改不会导致任何移动,因为元素已经完美地定位。

解决方案:设置Margin="-1000000"

所以在下面的代码中,这两个椭圆都居中于(200, 200)点。第一个椭圆具有与椭圆中心对应的LeftTop属性,允许轻松将它们绑定到其他对象的属性。

<Canvas>
    <Ellipse Width="100" Height="100" Canvas.Left="200" Canvas.Top="200" Opacity="0.5" Fill="Red" Margin="-100000" />
    <Ellipse Width="100" Height="100" Canvas.Left="150" Canvas.Top="150" Opacity="0.5" Fill="Blue" />
</Canvas>

不好的是,这个解决方案只适用于WPF。Silverlight和WinRT没有描述的行为。


太棒了!非常感谢! - Martin Zikmund

4
更简单的方法,至少对于形状来说,是使用具有适当几何形状的路径:
<Canvas>
    <Path Canvas.Left="200" Canvas.Top="200" Fill="Red" Opacity="0.5">
        <Path.Data>
            <EllipseGeometry RadiusX="50" RadiusY="50"/>
        </Path.Data>
    </Path>
</Canvas>

1
我通过将画布放入一个2x2的网格的右下角单元格中来解决了这个问题。这使得0,0坐标成为网格的中心,然后您可以相对于该中心进行所有绘图。

你能发一下你的 XAML 吗? - Scott Baker
这个问题并不是在问如何将物品相对于画布中心放置;而是在问如何使用 Canvas.TopCanvas.Left 将物品放置在画布中(相对于物品的中心)。 - Mike Nakis

0

我已经提到了这样的解决方案。正如我所说,我想要一个完全声明性的仅限XAML的解决方案。 - Ark-kun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接