Alinhamento vertical de texto no WPF TextBlock

228

Como atribuir alinhamento central vertical ao texto dentro de um TextBlock? Encontrei a propriedade TextAlignment, mas é para alinhamento horizontal de texto. Como faço para alinhamento vertical de texto?

Formiga
fonte
@shr e outros: observe que TextAlignmentafeta apenas o alinhamento horizontal, não o vertical (como a pergunta se refere).
de Drew Noakes

Respostas:

284

Um bloco de texto em si não pode fazer o alinhamento vertical

A melhor maneira de fazer isso é encontrar o bloco de texto dentro de uma borda, para que ela faça o alinhamento.

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

Nota: Isso é funcionalmente equivalente ao uso de uma grade, depende apenas de como você deseja que os controles se ajustem ao restante do layout e a qual deles é mais adequado

Orion Edwards
fonte
22
+1 A altura da borda deve ser definida para o alinhamento vertical entrar em vigor.
Tim Lloyd
21
Além disso, o TextBlock não pode ter uma altura especificada ou não será centralizado verticalmente.
pearcewg
20
@gav - TextAlignment só o alinhamento horizontal ... a pergunta é sobre alinhamento vertical
Orion Edwards
@ TimLloyd - Não sei se isso é sempre verdade. Eu tenho essa configuração, a borda tem a altura "Auto" e está funcionando bem. Está em uma célula de grade com alturas de linha com estrela (e outras coisas na linha).
Bob Sammers
97

Embora o Orion Edwards Answer funcione em qualquer situação, pode ser difícil adicionar a borda e definir as propriedades da borda sempre que você desejar fazer isso. Outra maneira rápida é definir o preenchimento do bloco de texto:

<TextBlock Height="22" Padding="3" />
Ben Jones
fonte
11
Eu acho que essa é a resposta mais brilhante.
Boppity Bop
1
Isso só funciona se a fonte tiver um tamanho de 16px, não é?
C4d #
1
A resposta aceita alinhará verticalmente corretamente as bordas reais do TextBox, mas não parece ter um efeito no texto real dentro do qual ... tenho certeza que é a intenção do OP. Esta solução funciona no lugar de uma propriedade TextVerticalAlignment adequada e recebe meu voto positivo. :)
Trekkie
E quanto ao conteúdo dinâmico dentro do bloco, 2 ou 5 linhas não exigem preenchimento diferente, também fontes 10pt vs 24pt
Reahreic
57

O TextBlock não suporta alinhamento vertical de texto.

Eu trabalho em torno disso, envolvendo o bloco de texto com uma grade e definindo HorizontalAlignment = "Stretch" e VerticalAlignment = "Center".

Como isso:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>
hwiechers
fonte
+1 nem precisa definir a altura para a grade, como na abordagem baseada em borda.
Efran Cobisi 21/07
Eu achei que essa abordagem funciona melhor para mim. Estou criando luzes indicadoras dinâmicas sobrepondo TextBlock-as Ellipsea Grid. Não há necessidade de vincular minhas propriedades de largura e altura ou fazer algo complicado.
arroz
17

Você pode usar o rótulo em vez do bloco de texto.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>
Aneesh Daniel
fonte
3
Bom, o Label possui VerticalContentAlignment. Greeeat. +1
Ignacio Soler Garcia
3
Não está claro se o OP precisava usar um TextBlock ou poderia se safar com um Label. Usar uma etiqueta funcionou para o que eu precisava. 1
Steve Kalemkiewicz
19
Isso responde à pergunta como produzir texto vertical, não como aplicar alinhamento vertical!
Sebastian Negraszus
26
Esta questão está sendo discutida em meta: meta.stackoverflow.com/questions/305572/…
NathanOliver 8/15
6

Se você pode ficar sem a quebra de texto , acho que substituir o TextBlock por um Label é a maneira mais sucinta de fazer isso. Caso contrário, siga uma das outras respostas válidas.

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

TextBlocknão suporta alinhamento vertical de seu conteúdo. Se você deve usar TextBlock, você deve alinhá-lo em relação ao pai.

No entanto, se você puder usar Label(e eles têm uma funcionalidade muito semelhante), poderá posicionar o conteúdo do texto:

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

A Labelextensão será esticada para preencher seus limites por padrão, o que significa que o texto do rótulo será centralizado.

Drew Noakes
fonte
3

Para mim, VerticalAlignment="Center"corrige esse problema.
Isso pode ser porque o TextBlockpacote está envolvido em uma grade, mas praticamente tudo está no wpf.

user448777
fonte
1

Descobri que modificar o estilo da caixa de texto (por exemplo:) controltemplatee, em seguida, modificar o PART_ContentHostalinhamento vertical para o Centro, fará o truque

JLuis Estrada
fonte
O OP está perguntando sobre os TextBlocks. Eles não têm ControlTemplates.
ANeves 12/07
1

Apenas para rir, dê um giro neste XAML. Não é perfeito, pois não é um 'alinhamento', mas permite ajustar o alinhamento do texto dentro de um parágrafo.

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

Se você pode ignorar a altura do TextBlock, é melhor você usar isso:

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

No meu caso, fiz isso para tornar a TextBlockexibição mais agradável.

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

O truque para tornar o texto mais distante da base é definir

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

Eu achei que tinha que fazer um pouco diferente. Meu problema era que, se eu alterasse o tamanho da fonte, o texto seria movido para cima na caixa de texto em vez de permanecer na parte inferior com o restante das caixas de texto na linha. Ao alterar o alinhamento vertical de cima para baixo, fui capaz de alterar programaticamente a fonte do tamanho 20 para o tamanho 14 e posterior, mantendo a gravidade do texto na parte inferior e mantendo as coisas organizadas. Aqui está como:

insira a descrição da imagem aqui

Dave S.
fonte
0

TextBox de linha única alinhada verticalmente.

Para expandir a resposta fornecida pelo @Orion Edwards, é assim que você faria totalmente a partir do code-behind (nenhum estilo definido). Basicamente, crie uma classe personalizada que herda de Border com seu filho definido como TextBox. O exemplo abaixo pressupõe que você deseja apenas uma única linha e que a borda é filha de uma tela. Também assume que você precisaria ajustar a propriedade MaxLength do TextBox com base na largura da borda. O exemplo abaixo também define o cursor da borda para imitar uma caixa de texto, configurando-o para o tipo 'IBeam'. Uma margem de '3' é definida para que o TextBox não esteja absolutamente alinhado à esquerda da borda.

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

Classe:

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

Eu acho que é melhor usar um Label (ou TextBlock) em um Label, você não pode anexar um evento de mouse diretamente no controle de borda, finalmente ele está anexado no TextBlock, esta é minha recomendação:

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

Eu acho que é aconselhável usar uma caixa de texto sem borda e plano de fundo como uma maneira fácil e rápida de alcançar o bloco de texto alinhado ao centro

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>
StudioX
fonte
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Bastianon Massimo
fonte
1
A questão era para um TextBlock, não TextBox. -1
KnorxThieus