15

WPF Canvas 有一个坐标系,从控件左上角的 (0,0) 开始。

例如,设置以下内容将使我的控件出现在左上角:

<Control Canvas.Left="0" Canvas.Top="0">

如何将其更改为标准笛卡尔坐标

基本上:

  • (0,0) 在中心
  • 翻转Y

我注意到这篇文章很相似,但它没有谈论翻译坐标系。我尝试添加 TranslateTransform,但无法使其工作。

4

4 回答 4

30

无需创建自定义面板。帆布会做得很好。只需将其包裹在另一个控件(例如边框)中,居中,使其大小为零,然后使用 RenderTransform 翻转它:

<Border>
  <Canvas HorizontalAlignment="Center" VerticalAlignment="Center"
          Width="0" Height="0"
          RenderTransform="1 0 0 -1 0 0">
    ...
  </Canvas>
</Border>

您可以这样做,画布中的所有内容仍会出现,除了 (0,0) 将位于包含控件的中心(在本例中为边框的中心)并且 +Y 将向上而不是向下。

同样,无需为此创建自定义面板。

于 2009-12-27T05:24:44.527 回答
7

这很容易做到。我使用 .NET Reflector 查看了 Canvas 的原始代码,发现实现实际上非常简单。唯一需要的是覆盖该功能ArrangeOverride(...)

public class CartesianCanvas : Canvas
{
    public CartesianCanvas()
    {
        LayoutTransform = new ScaleTransform() { ScaleX = 1, ScaleY = -1 };
    }
    protected override Size ArrangeOverride( Size arrangeSize )
    {
        Point middle = new Point( arrangeSize.Width / 2, arrangeSize.Height / 2 );

        foreach( UIElement element in base.InternalChildren )
        {
            if( element == null )
            {
                continue;
            }
            double x = 0.0;
            double y = 0.0;
            double left = GetLeft( element );
            if( !double.IsNaN( left ) )
            {
                x = left;
            }

            double top = GetTop( element );
            if( !double.IsNaN( top ) )
            {
                y = top;
            }

            element.Arrange( new Rect( new Point( middle.X + x, middle.Y + y ), element.DesiredSize ) );
        }
        return arrangeSize;
    }
}
于 2009-12-10T02:36:48.493 回答
7

您可以简单地使用 更改原点RenderTransformOrigin

    <Canvas Width="Auto" Height="Auto"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            RenderTransformOrigin="0.5,0.5">
        <Canvas.RenderTransform>
            <TransformGroup>
                <ScaleTransform ScaleY="-1" ScaleX="1" />
            </TransformGroup>
        </Canvas.RenderTransform>
    </Canvas>
于 2014-01-06T01:14:40.447 回答
5

最好的办法是编写一个自定义的 Canvas,您可以在其中编写 ArrangeOverride,使其以 0,0 为中心。

更新:我在下面的答案中给出了另一条评论(@decasteljau)我不建议从 Canvas 派生,您可以从 Panel 派生并添加两个附加依赖属性 Top 和 Left 并放置您在上面粘贴的相同代码。也不需要其中包含 LayoutTransform 的构造函数,并且不要在面板代码上使用任何变换,使用适当的度量并根据面板的 DesiredSize 进行排列,这样您也可以获得很好的内容调整大小行为。当 Canvas 大小更改时,Canvas 不会动态定位项目。

于 2009-12-09T04:18:09.677 回答