在 WPF 中仅使用 XAML 将元素按其中心(而不是左上角)定位在画布内 [英] Positioning an element inside the Canvas by its center (instead of the top left corner) using only XAML in WPF
问题描述
关于在 Canvas
中定位元素的常见问题是如何定位元素的中心(而不是左上角)".
The common question about positioning an element inside a Canvas
is "How to position the center of element (instead of the top left corner)".
提出了几种解决方案,但它们都有缺点.
Several solutions are presented, but they all have drawbacks.
最简单的解决方案是在以编程方式设置 Canvas.Left
和 Canvas.Top
属性时适应元素大小.这有效,但只有一次.此解决方案不支持绑定,并且会在元素大小更改时中断.您也不能使用
The easiest solution is to accommodate the element size during while setting the Canvas.Left
and Canvas.Top
properties programmatically. This works, but only once. This solution doesn't support bindings and it will break when the element size is changed. You also cannot set the Canvas.Left
or Canvas.Top
using
另一组解决方案涉及使用RenderTransform
或Margin
的翻译转换.这些解决方案需要将某些属性绑定到 -0.5 * Width
或 -0.5 * Height
.这种绑定需要创建一个自定义的 ValueConverter
,并且不可能只使用 XAML 来创建.
Another set of solutions involve translate transformations utilizing either RenderTransform
or Margin
. These solutions require binding some property to the -0.5 * Width
or -0.5 * Height
. Such binding requires creating a custom ValueConverter
and is impossible to create using only XAML.
那么,有没有一种简单的方法可以在画布内定位元素,使其 Canvas.Left
和 Canvas.Top
对应于元素的中心,并且两者都对应size 和 position 属性可以绑定到其他一些属性吗?
So, is there a simple way to position an element inside canvas so that its Canvas.Left
and Canvas.Top
correspond to the element's center and both size and position properties can be bound to some other properties?
推荐答案
XAML 和绑定看起来非常强大,但有时也存在需要非常复杂的解决方案的简单问题.在我的绑定库中,创建这样的绑定就像编写 element.Center = position
或 element.TopLeft = position - element.Size/2
一样简单,但不要让我得意忘形了.
XAML and bindings seem very powerful, but sometimes there are simple problems that require very complex solutions. In my bindings library creating such binding would be as easy as writing element.Center = position
or element.TopLeft = position - element.Size / 2
, but don't let me get carried away.
我找到了一个非常简单的解决方案,它只使用 XAML 并支持绑定元素的大小和位置属性.似乎当 WPF 控件的对齐设置太 Stretch
或 Center
被放置在画布内时,元素倾向于"居中作为 (Canvas.Left, Canvas.Top)
点(我们想要的状态),但是被放置在同一个 (Canvas.Left, Canvas.Top)
点的角板"挡住了.我怎么知道这个引力"?当您通过将元素的 Margin
设置为负值来缓和块时,这很明显.设置负边距允许元素向其中心目标移动.元素移动直到 Margin
到达 (-Height/2, -Width/2)
以便元素完美地居中于 (Canvas.Left, Canvas.Top)
点.进一步的变化不会引起任何移动,因为元素已经完美定位.
I've found a very simple solution which uses only XAML and supports binding both size and position properties of the element. It seems that when the WPF control with alignment set too Stretch
or Center
is placed inside the canvas, the element "gravitates" towards centering as the (Canvas.Left, Canvas.Top)
point (the state that we desire), but is stopped by the "angle plate" placed at the same (Canvas.Left, Canvas.Top)
point. How do I know about this "gravitation"? It's evident when you ease the block by setting the Margin
of the element to a negative value. Setting the negative margin allows the element to move towards its center goal. The element moves until the Margin
reaches (-Height / 2, -Width / 2)
so that the element becomes perfectly centered at the (Canvas.Left, Canvas.Top)
point. Further changes don't cause any movement since the element is already perfectly positioned.
解决方案:设置Margin="-1000000"
.
所以在下面的代码中,椭圆都以 (200, 200) 点为中心.第一个椭圆具有与椭圆中心相对应的 Left
和 Top
属性,可以轻松地将它们与其他一些对象的属性绑定.
So in the following code the ellipses are both centered at the (200, 200) point. The first ellipse has Left
and Top
properties corresponding to the ellipse center allowing to easily bind them with some other objects' properties.
<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 没有描述的行为.
The bad thing is this solution only work in WPF. Silverlight and WinRT don't have the described behavior.
这篇关于在 WPF 中仅使用 XAML 将元素按其中心(而不是左上角)定位在画布内的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!