Puede lograr esto vinculando el margen de la etiqueta a ActualWidth
y ActualHeight
de la etiqueta y multiplicando estos valores por -0.5. Esto mueve la etiqueta a la mitad de su ancho; y mueve la etiqueta hacia arriba a la mitad de su altura.
Aquí es un ejemplo:
XAML:
<Window x:Class="CenteredLabelTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CenteredLabelTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:CenterConverter x:Key="centerConverter"/>
</Window.Resources>
<Canvas>
<TextBlock x:Name="txt" Canvas.Left="40" Canvas.Top="40" TextAlignment="Center" Text="MMMMMM">
<TextBlock.Margin>
<MultiBinding Converter="{StaticResource centerConverter}">
<Binding ElementName="txt" Path="ActualWidth"/>
<Binding ElementName="txt" Path="ActualHeight"/>
</MultiBinding>
</TextBlock.Margin>
</TextBlock>
<Rectangle Canvas.Left="39" Canvas.Top="39" Width="2" Height="2" Fill="Red"/>
</Canvas>
</Window>
Los aspectos más destacados rectángulo rojo la coordenada (40, 40) sobre el que se centra la etiqueta "MMMMMM".
Convertidor:
public class CenterConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] == DependencyProperty.UnsetValue || values[1] == DependencyProperty.UnsetValue)
{
return DependencyProperty.UnsetValue;
}
double width = (double) values[0];
double height = (double)values[1];
return new Thickness(-width/2, -height/2, 0, 0);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
El resultado es el siguiente:
Con el fin de hacer que la programación, defina una propiedad adjunta Mover.MoveToMiddle
, así:
public class Mover : DependencyObject
{
public static readonly DependencyProperty MoveToMiddleProperty =
DependencyProperty.RegisterAttached("MoveToMiddle", typeof (bool), typeof (Mover),
new PropertyMetadata(false, PropertyChangedCallback));
public static void SetMoveToMiddle(UIElement element, bool value)
{
element.SetValue(MoveToMiddleProperty, value);
}
public static bool GetMoveToMiddle(UIElement element)
{
return (bool) element.GetValue(MoveToMiddleProperty);
}
private static void PropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (element == null)
{
return;
}
if ((bool)e.NewValue)
{
MultiBinding multiBinding = new MultiBinding();
multiBinding.Converter = new CenterConverter();
multiBinding.Bindings.Add(new Binding("ActualWidth") {Source = element});
multiBinding.Bindings.Add(new Binding("ActualHeight") {Source = element});
element.SetBinding(FrameworkElement.MarginProperty, multiBinding);
}
else
{
element.ClearValue(FrameworkElement.MarginProperty);
}
}
}
configuración Mover.MoveToMiddle
a true
significa que el margen de ese elemento de marco se vincula automáticamente a su ancho y altura real de modo que el elemento de marco se mueva a su punto central.
que usaría en su código XAML como esto:
<Window x:Class="CenteredLabelTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CenteredLabelTest"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:CenterConverter x:Key="centerConverter"/>
</Window.Resources>
<Canvas>
<TextBlock Canvas.Left="40" Canvas.Top="40" TextAlignment="Center" Text="MMMMMM"
local:Mover.MoveToMiddle="True"/>
<Rectangle Canvas.Left="39" Canvas.Top="39" Width="2" Height="2" Fill="Red"/>
</Canvas>
</Window>
Una alternativa sería la de obligar a RenderTransform
en lugar de Margin
. En este caso, el convertidor volvería
return new TranslateTransform(-width/2, -height/2);
y el método de devolución de llamada de la propiedad adjunta contendría estas líneas:
if ((bool)e.NewValue)
{
...
element.SetBinding(UIElement.RenderTransformProperty, multiBinding);
}
else
{
element.ClearValue(UIElement.RenderTransformProperty);
}
Esta alternativa tiene la ventaja de que el efecto de la propiedad adjunta es visible en el Visual Diseñador de estudio (que no es el caso cuando se establece la propiedad Margen).
personas Puede ver estas respuestas y pensar que es demasiado complicado para los simples requisitos de la pregunta, pero esto no solo le muestra cómo centrar una etiqueta. Este código define un comportamiento que centrará cualquier 'FrameworkElement' en un punto y lo mantendrá centrado, incluso cuando el tamaño de ese elemento pueda estar cambiando. –
Esto funciona realmente bien. Desde XAML el uso es: Observe la conversión automática de "100,100" a Point. –
Funciona perfectamente, incluso con XAML que no sea WPF, p. Ej. Windows 10 universal, gracias! –