5

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.

Is there a simple (XAML-only) method 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?

I've found a very easy way to do this in WPF (just set Margin="-1000000" Positioning an element inside the Canvas by its center (instead of the top left corner) using only XAML in WPF), but it doesn't work for Silverlight/WinRT. The only other method that I know requires creating ValueConverter to perform the x *= -0.5 calculation (which is not XAML-only).

Community
  • 1
  • 1
Ark-kun
  • 6,358
  • 2
  • 34
  • 70
  • Does this answer your question? [Positioning an element inside the Canvas by its center (instead of the top left corner) using only XAML in WPF](https://stackoverflow.com/questions/13219321/positioning-an-element-inside-the-canvas-by-its-center-instead-of-the-top-left) – Mike Nakis May 23 '23 at 10:56

1 Answers1

2

While it's not pretty, here's an example of using nested RenderTransforms with different origins to offset the position of the object to make it so that it's centered:

<UserControl x:Class="UrlTest.Center"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Canvas x:Name="LayoutRoot" Background="White">
        <ContentControl Canvas.Top="100" Content="{Binding ActualWidth,ElementName=Center, StringFormat=Width \{0\}}"/>
        <ContentControl Canvas.Top="120" Content="{Binding ActualHeight,ElementName=Center, StringFormat=Height \{0\}}"/>
        <Grid x:Name="Center" RenderTransformOrigin="-.5,-.5" Canvas.Left="40" Canvas.Top="25">
            <Grid.RenderTransform>
                <ScaleTransform ScaleX="-1" ScaleY="-1"/>
            </Grid.RenderTransform>
            <Grid RenderTransformOrigin="-.25,-.25">
                <Grid.RenderTransform>
                    <ScaleTransform ScaleX="-1" ScaleY="-1"/>
                </Grid.RenderTransform>
                <Ellipse Width="80" Height="50" Fill="Aquamarine"/>
                <ContentControl FontSize="20" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">Center</ContentControl>
            </Grid>
        </Grid>
    </Canvas>
</UserControl>

The inner Grids are for creating the transforms, while the outer Canvas is there to make sure the Grid inside of it sets its size to that of the content inside of it.

Gabe
  • 84,912
  • 12
  • 139
  • 238
  • Pretty ingenious! I've tried to solve the system of several transformation equations to come to a solution like this, but failed. These double transform does the deal nicely. P.S. The RenderTransformOrigin values can also be `0,0`; `0.25,0.25` or `-0.25,-0.25`; `0,0`. They just need to satisfy the `Internal - External = 1/4` equation. – Ark-kun May 28 '13 at 00:55