wpf xaml canvas centering

Posicionar un elemento dentro del Lienzo por su centro(en lugar de la esquina superior izquierda) usando solo XAML en WPF



canvas centering (4)

Aún más simple, al menos para Shapes, sería usar un Path con una Geometría apropiada:

<Canvas> <Path Canvas.Left="200" Canvas.Top="200" Fill="Red" Opacity="0.5"> <Path.Data> <EllipseGeometry RadiusX="50" RadiusY="50"/> </Path.Data> </Path> </Canvas>

La pregunta común sobre el posicionamiento de un elemento dentro de un Canvas es "Cómo colocar el centro del elemento (en lugar de la esquina superior izquierda)".

Se presentan varias soluciones, pero todas tienen inconvenientes.

La solución más fácil es acomodar el tamaño del elemento durante la configuración de las propiedades Canvas.Left y Canvas.Top programación. Esto funciona, pero solo una vez. Esta solución no admite enlaces y se romperá cuando se cambie el tamaño del elemento. Tampoco puede establecer Canvas.Left o Canvas.Top usando

Otro conjunto de soluciones implica transformaciones de traducción que utilizan RenderTransform o Margin . Estas soluciones requieren vincular alguna propiedad al -0.5 * Width o -0.5 * Height . Tal enlace requiere crear un ValueConverter personalizado y es imposible de crear usando solo XAML.

Entonces, ¿hay una manera simple de posicionar un elemento dentro del lienzo para que Canvas.Left y Canvas.Top correspondan al centro del elemento y las propiedades de tamaño y posición se puedan vincular a otras propiedades?


XAML y enlaces parecen muy poderosos, pero a veces hay problemas simples que requieren soluciones muy complejas. En mi librería de enlaces, crear tal enlace sería tan fácil como escribir element.Center = position o element.TopLeft = position - element.Size / 2 , pero no dejes que me deje llevar.

Encontré una solución muy simple que usa solo XAML y admite el enlace de las propiedades de tamaño y posición del elemento. Parece que cuando el control WPF con la alineación establecida demasiado Stretch o Center se coloca dentro del lienzo, el elemento "gravita" hacia el centro como el punto (Canvas.Left, Canvas.Top) (el estado que deseamos), pero se detiene por la "placa de ángulo" colocada en el mismo punto (Canvas.Left, Canvas.Top) . ¿Cómo sé acerca de esta "gravitación"? Es evidente cuando se facilita el bloqueo al establecer el Margin del elemento a un valor negativo. Establecer el margen negativo permite que el elemento se mueva hacia su objetivo central. El elemento se mueve hasta que el Margin alcance (-Height / 2, -Width / 2) para que el elemento quede perfectamente centrado en el punto (Canvas.Left, Canvas.Top) . Los cambios adicionales no causan ningún movimiento ya que el elemento ya está perfectamente posicionado.

Solución: configure Margin="-1000000" .

Entonces, en el siguiente código, las elipsis se centran en el punto (200, 200). La primera elipse tiene las propiedades Left y Top correspondientes al centro de la elipse, lo que permite vincularlas fácilmente con algunas propiedades de otros objetos.

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

Lo malo es que esta solución solo funciona en WPF. Silverlight y WinRT no tienen el comportamiento descrito.


Lo resolví colocando el lienzo en la celda inferior derecha de una grilla de 2x2. Eso hace que el 0,0 coordine el centro de la cuadrícula, y luego puedes hacer todo tu dibujo relativo a eso.