Alineación vertical de texto en WPF TextBlock

228

¿Cómo asigno la alineación central vertical al texto dentro de un TextBlock? Encontré la propiedad TextAlignment pero es para la alineación horizontal del texto. ¿Cómo lo hago para la alineación vertical del texto?

Hormiga
fuente
@shr y otros: tenga en cuenta que TextAlignmentsolo afecta la alineación horizontal, no la alineación vertical (como se refiere a la pregunta).
Drew Noakes

Respuestas:

284

Un bloque de texto en sí no puede hacer una alineación vertical

La mejor manera de hacer esto que he encontrado es colocar el bloque de texto dentro de un borde, para que el borde se alinee por usted.

<Border BorderBrush="{x:Null}" Height="50">
    <TextBlock TextWrapping="Wrap" Text="Some Text" VerticalAlignment="Center"/>
</Border>

Nota: Esto es funcionalmente equivalente al uso de una cuadrícula, solo depende de cómo desee que los controles encajen con el resto de su diseño en cuanto a cuál es más adecuado

Orion Edwards
fuente
22
+1 La altura del borde debe establecerse para que la alineación vertical surta efecto.
Tim Lloyd
21
Además, TextBlock no puede tener una altura especificada, o no se centrará verticalmente.
pearcewg
20
@gav - TextAlignment solo realiza la alineación horizontal ... la pregunta es sobre la alineación vertical
Orion Edwards
@TimLloyd: no estoy seguro de que eso sea siempre cierto. Tengo esta configuración, el borde tiene una altura "Auto" y está funcionando bien. Está en una celda de cuadrícula con alturas de fila destacadas (y otras cosas en la fila).
Bob Sammers
97

Si bien Orion Edwards Answer funciona para cualquier situación, puede ser difícil agregar el borde y establecer las propiedades del borde cada vez que desee hacer esto. Otra forma rápida es establecer el relleno del bloque de texto:

<TextBlock Height="22" Padding="3" />
Ben Jones
fuente
11
Creo que esta es la respuesta más brillante.
Boppity Bop
1
¿Esto solo funciona si la fuente tiene un tamaño de 16px?
C4d
1
La respuesta aceptada alineará verticalmente correctamente los bordes reales de TextBox, pero no parece tener un efecto en el texto real dentro ... lo cual estoy bastante seguro de que es la intención del OP. Esta solución funciona en lugar de una propiedad TextVerticalAlignment adecuada y obtiene mi voto a favor. :)
Trekkie
¿Qué pasa con el contenido dinámico dentro del bloque? ¿No requerirían 2 o 5 líneas de relleno diferente, también fuentes de 10pt frente a 24pt?
Reahreic
57

TextBlock no admite la alineación vertical de texto.

Evito esto envolviendo el bloque de texto con una cuadrícula y configurando HorizontalAlignment = "Stretch" y VerticalAlignment = "Center".

Me gusta esto:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>
hwiechers
fuente
+1 ni siquiera necesita establecer la altura para la cuadrícula, como con el enfoque basado en bordes.
Efran Cobisi
Encontré que este enfoque funciona mejor para mí. Estoy creando indicadores luminosos dinámicos mediante la superposición TextBlocken Ellipseel interior de una Grid. No es necesario vincular mis propiedades de ancho y alto ni hacer nada complicado.
arroz
17

Puede usar la etiqueta en lugar del bloque de texto.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>
Aneesh Daniel
fuente
3
Agradable, la etiqueta tiene VerticalContentAlignment. Greeeat +1
Ignacio Soler Garcia
3
No está claro si el OP necesitaba usar un TextBlock o podría salirse con una Etiqueta. Usar una etiqueta funcionó para lo que necesitaba. +1
Steve Kalemkiewicz
19
¡Esto responde a la pregunta de cómo producir texto vertical, no cómo aplicar la alineación vertical!
Sebastian Negraszus
26
Esta pregunta se está discutiendo en meta: meta.stackoverflow.com/questions/305572/…
NathanOliver
6

Si puede prescindir del ajuste de texto , creo que reemplazar TextBlock con una etiqueta es la forma más sucinta de hacerlo. De lo contrario, siga una de las otras respuestas válidas.

<Label Content="Some Text" VerticalAlignment="Center"/>
Mike Fuchs
fuente
6

TextBlockno admite la alineación vertical de su contenido. Si debes usarTextBlock alinearlo con respecto a su padre.

Sin embargo, si puede usar Labelen su lugar (y tienen una funcionalidad muy similar), puede colocar el contenido del texto:

<Label VerticalContentAlignment="Center" HorizontalContentAlignment="Center">
   I am centred text!
</Label>

El Labelse estirará para llenar sus límites de forma predeterminada, lo que significa que el texto de la etiqueta estará centrado.

Drew Noakes
fuente
3

Para mí, VerticalAlignment="Center"soluciona este problema.
Esto podría deberse a que TextBlockestá envuelto en una cuadrícula, pero también lo está prácticamente todo en wpf.

usuario448777
fuente
1

Descubrí que modificar el estilo del cuadro de texto (es decir:) controltemplatey luego modificar la PART_ContentHostalineación vertical al Centro hará el truco

JLuis Estrada
fuente
OP pregunta sobre TextBlocks. No tienen ControlTemplates.
ANeves
1

Solo por risas, dale un giro a este XAML. No es perfecto, ya que no es una "alineación", pero le permite ajustar la alineación del texto dentro de un párrafo.

<TextBlock>
    <TextBlock BaselineOffset="30">One</TextBlock>
    <TextBlock BaselineOffset="20">Two</TextBlock>  
    <Run>Three</Run>            
    <Run BaselineAlignment="Subscript">Four</Run>   
</TextBlock>
Gusdor
fuente
1

Si puede pasar por alto la altura de TextBlock, es mejor que use esto:

<TextBlock Height="{Binding}" Text="Your text"
TextWrapping="Wrap" VerticalAlignment="Center" Width="28"/>
fa wildchild
fuente
1

En mi caso, hice esto para que la TextBlockpantalla fuera más agradable.

<Border BorderThickness="3" BorderBrush="Yellow" CornerRadius="10" Padding="2"
    HorizontalAlignment="Center" VerticalAlignment="Center" Height="30" Width="150">
        <TextBlock FontSize="20" Height="23" HorizontalAlignment="Left" Margin="0,0,0,-5" Text="" VerticalAlignment="Top" Width="141" Background="White" />
</Border>

El truco para alejar el texto del fondo es establecer

Margin="0,0,0,-5"
Brandon Gao
fuente
0

Descubrí que tenía que hacerlo un poco diferente. Mi problema era que si cambiaba el tamaño de fuente, el texto se movería hacia arriba en el cuadro de texto en lugar de permanecer en la parte inferior con el resto de cuadros de texto en la línea. Al cambiar la alineación vertical de arriba a abajo, pude cambiar la fuente mediante programación del tamaño 20 al tamaño 14 y viceversa, manteniendo la gravedad del texto en la parte inferior y manteniendo las cosas ordenadas. Así es cómo:

ingrese la descripción de la imagen aquí

Dave S.
fuente
0

Cuadro de texto de línea única alineado verticalmente.

Para ampliar la respuesta proporcionada por @Orion Edwards, así es como lo haría completamente desde el código subyacente (sin estilos establecidos). Básicamente, cree una clase personalizada que herede de Border que tenga su elemento secundario establecido en un cuadro de texto. El siguiente ejemplo supone que solo desea una sola línea y que el borde es hijo de un lienzo. También supone que necesitaría ajustar la propiedad MaxLength de TextBox según el ancho del borde. El siguiente ejemplo también establece el cursor del borde para imitar un cuadro de texto estableciéndolo en el tipo 'IBeam'. Se establece un margen de '3' para que TextBox no esté absolutamente alineado a la izquierda del borde.

double __dX = 20;
double __dY = 180;
double __dW = 500;
double __dH = 40;
int __iMaxLen = 100;

this.m_Z3r0_TextBox_Description = new CZ3r0_TextBox(__dX, __dY, __dW, __dH, __iMaxLen, TextAlignment.Left);
this.Children.Add(this.m_Z3r0_TextBox_Description);

Clase:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;


namespace ifn0tz3r0Exp
{
    class CZ3r0_TextBox : Border
    {
        private TextBox m_TextBox;

        private SolidColorBrush m_Brush_Green = new SolidColorBrush(Colors.MediumSpringGreen);
        private SolidColorBrush m_Brush_Black = new SolidColorBrush(Colors.Black);
        private SolidColorBrush m_Brush_Transparent = new SolidColorBrush(Colors.Transparent);

        public CZ3r0_TextBox(double _dX, double _dY, double _dW, double _dH, int _iMaxLen, TextAlignment _Align)
        {

            /////////////////////////////////////////////////////////////
            //TEXTBOX
            this.m_TextBox = new TextBox();
            this.m_TextBox.Text = "This is a vertically centered one-line textbox embedded in a border...";
            Canvas.SetLeft(this, _dX);
            Canvas.SetTop(this, _dY);
            this.m_TextBox.FontFamily = new FontFamily("Consolas");
            this.m_TextBox.FontSize = 11;
            this.m_TextBox.Background = this.m_Brush_Black;
            this.m_TextBox.Foreground = this.m_Brush_Green;
            this.m_TextBox.BorderBrush = this.m_Brush_Transparent;
            this.m_TextBox.BorderThickness = new Thickness(0.0);
            this.m_TextBox.Width = _dW;
            this.m_TextBox.MaxLength = _iMaxLen;
            this.m_TextBox.TextAlignment = _Align;
            this.m_TextBox.VerticalAlignment = System.Windows.VerticalAlignment.Center;
            this.m_TextBox.FocusVisualStyle = null;
            this.m_TextBox.Margin = new Thickness(3.0);
            this.m_TextBox.CaretBrush = this.m_Brush_Green;
            this.m_TextBox.SelectionBrush = this.m_Brush_Green;
            this.m_TextBox.SelectionOpacity = 0.3;

            this.m_TextBox.GotFocus += this.CZ3r0_TextBox_GotFocus;
            this.m_TextBox.LostFocus += this.CZ3r0_TextBox_LostFocus;
            /////////////////////////////////////////////////////////////
            //BORDER

            this.BorderBrush = this.m_Brush_Transparent;
            this.BorderThickness = new Thickness(1.0);
            this.Background = this.m_Brush_Black;            
            this.Height = _dH;
            this.Child = this.m_TextBox;
            this.FocusVisualStyle = null;
            this.MouseDown += this.CZ3r0_TextBox_MouseDown;
            this.Cursor = Cursors.IBeam;
            /////////////////////////////////////////////////////////////
        }
        private void CZ3r0_TextBox_MouseDown(object _Sender, MouseEventArgs e)
        {
            this.m_TextBox.Focus();
        }
        private void CZ3r0_TextBox_GotFocus(object _Sender, RoutedEventArgs e)
        {
            this.BorderBrush = this.m_Brush_Green;
        }
        private void CZ3r0_TextBox_LostFocus(object _Sender, RoutedEventArgs e)
        {
            this.BorderBrush = this.m_Brush_Transparent;
        }
    }
}
Aaron
fuente
0

Creo que es mejor usar una Etiqueta (o TextBlock) en una Etiqueta, no puede adjuntar un evento de mouse directamente en el control de borde, finalmente se adjunta en TextBlock, esta es mi recomendación:

<Label 
    Height="32"
    VerticalContentAlignment="Center"
    HorizontalContentAlignment="Stretch"
    MouseLeftButtonUp="MenuItem_MouseLeftButtonUp">
    <TextBlock Padding="32 0 10 0">
        Label with click event
    </TextBlock>
</Label>
acamro
fuente
0

Creo que es aconsejable usar un cuadro de texto sin borde ni fondo como una forma fácil y rápida de llegar al bloque de texto alineado al centro

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>
StudioX
fuente
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Bastianon Massimo
fuente
1
La pregunta era por un TextBlock, no TextBox. -1
KnorxThieus