Allineamento verticale del testo in WPF TextBlock


228

Come posso assegnare l'allineamento centrale verticale al testo all'interno di un blocco testo? Ho trovato la proprietà TextAlignment ma è per l'allineamento orizzontale del testo. Come lo faccio per l'allineamento del testo verticale?


@shr e altri: nota che TextAlignmentinfluisce solo sull'allineamento orizzontale, non sull'allineamento verticale (come indicato dalla domanda).
Drew Noakes,

Risposte:


284

Un blocco di testo stesso non può eseguire l'allineamento verticale

Il modo migliore per farlo è quello di mettere il blocco di testo all'interno di un bordo, quindi il bordo fa l'allineamento per te.

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

Nota: questo è funzionalmente equivalente all'utilizzo di una griglia, dipende solo da come si desidera che i controlli si adattino al resto del layout su quale sia più adatto


22
+1 L'altezza del bordo deve essere impostata per rendere effettivo l'allineamento verticale.
Tim Lloyd,

21
Inoltre, TextBlock non può avere un'altezza specificata o non si centrerà verticalmente.
Pearcewg,

20
@gav - TextAlignment esegue solo l'allineamento orizzontale ... la domanda riguarda l'allineamento verticale
Orion Edwards,

@TimLloyd - Non sono sicuro che sia sempre vero. Ho questo set-up, il bordo ha l'altezza "Auto" e funziona benissimo. È in una cella a griglia con altezze di riga stellate (e altre cose nella riga).
Bob Sammers,

97

Mentre Orion Edwards Answer funziona in qualsiasi situazione, può essere una seccatura aggiungere il bordo e impostare le proprietà del bordo ogni volta che lo si desidera. Un altro modo rapido è quello di impostare il riempimento del blocco di testo:

<TextBlock Height="22" Padding="3" />

11
penso che questa sia la risposta più brillante.
Boppity Bop,

1
Funziona solo se il carattere ha una dimensione di 16 px no?
C4d,

1
La risposta accettata allinea correttamente correttamente i bordi effettivi di TextBox, ma non sembra avere un effetto sul testo reale all'interno ... che sono abbastanza sicuro dell'intento del PO. Questa soluzione funziona al posto di una proprietà TextVerticalAlignment corretta e ottiene il mio voto. :)
Trekkie,

Che dire dei contenuti dinamici all'interno del blocco, 2 o 5 righe non richiedono imbottiture diverse, anche caratteri 10pt contro 24pt
Reahreic

57

TextBlock non supporta l'allineamento verticale del testo.

Lavoro intorno a questo avvolgendo il blocco di testo con una griglia e impostando HorizontalAlignment = "Stretch" e VerticalAlignment = "Center".

Come questo:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>

+1 Non è nemmeno necessario impostare l'altezza per la griglia, come con l'approccio basato sul bordo.
Efran Cobisi,

Ho scoperto che questo approccio funziona meglio per me. Sto creando indicatore dinamico luci sovrapponendo TextBlocksu Ellipseall'interno di una Grid. Non c'è bisogno di legare le mie proprietà di larghezza e altezza o fare qualcosa di complicato.
Paddy,

17

È possibile utilizzare l'etichetta anziché il blocco testo.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>

3
Bene, l'etichetta ha VerticalContentAlignment. Greeeat. +1
Ignacio Soler Garcia,

3
Non è chiaro se l'OP doveva usare un TextBlock o poteva cavarsela con un'etichetta. Usare un'etichetta ha funzionato per quello che mi serviva. +1
Steve Kalemkiewicz,

19
Questo risponde alla domanda su come produrre testo verticale, non su come applicare l'allineamento verticale!
Sebastian Negraszus,

26
Questa domanda è in discussione su meta: meta.stackoverflow.com/questions/305572/…
NathanOliver

6

Se riesci a fare a meno del ritorno a capo automatico , penso che sostituire TextBlock con un'etichetta sia il modo più conciso per farlo. Altrimenti segui una delle altre risposte valide.

<Label Content="Some Text" VerticalAlignment="Center"/>

6

TextBlocknon supporta l'allineamento verticale del suo contenuto. Se devi usareTextBlock è necessario allinearlo rispetto al suo genitore.

Tuttavia, se è possibile utilizzare Labelinvece (e hanno funzionalità molto simili), è possibile posizionare il contenuto del testo:

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

Per Labelimpostazione predefinita, si allungherà per riempire i suoi limiti, il che significa che il testo dell'etichetta sarà centrato.


3

Per me, VerticalAlignment="Center"risolve questo problema.
Ciò potrebbe essere dovuto al fatto che TextBlockè racchiuso in una griglia, ma in pratica è praticamente tutto in wpf.


1

Ho scoperto che la modifica dello stile della casella di testo (ovvero:) controltemplatee quindi la modifica PART_ContentHostdell'allineamento verticale su Centro farà il trucco


OP chiede informazioni su TextBlocks. Non hanno ControlTemplates.
ANeves,

1

Solo per le risatine, dai a questo XAML un vortice. Non è perfetto in quanto non è un "allineamento" ma consente di regolare l'allineamento del testo all'interno di un paragrafo.

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

1

Se riesci a trascurare l'altezza di TextBlock, è meglio usare questo:

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

1

Nel mio caso, l'ho fatto per rendere il TextBlockdisplay più gradevole.

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

Il trucco per rendere il testo più lontano dal basso è impostare

Margin="0,0,0,-5"


0

Ho scoperto che dovevo farlo in modo leggermente diverso. Il mio problema era che se avessi cambiato la dimensione del carattere, il testo si sarebbe spostato verso l'alto nella TextBox invece di rimanere in fondo con il resto delle TextBox sulla riga. Modificando l'allineamento verticale dall'alto verso il basso sono stato in grado di cambiare il carattere programmaticamente dalla dimensione 20 alla dimensione 14 e ritorno, mantenendo la gravità del testo sul fondo e mantenendo le cose pulite. Ecco come:

inserisci qui la descrizione dell'immagine


0

TextBox a riga singola allineata verticalmente.

Per espandere la risposta fornita da @Orion Edwards, ecco come faresti completamente da code-behind (senza stili impostati). Fondamentalmente creare una classe personalizzata che eredita da Border che ha il suo Child impostato su TextBox. Nell'esempio seguente si presuppone che si desideri solo una singola linea e che il bordo sia figlio di una tela. Si presume inoltre che sia necessario regolare la proprietà MaxLength di TextBox in base alla larghezza del bordo. L'esempio seguente imposta anche il cursore del bordo per imitare una casella di testo impostandola sul tipo "IBeam". Viene impostato un margine di "3" in modo che TextBox non sia assolutamente allineato a sinistra del bordo.

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

0

Penso che sia meglio usare un'etichetta (o TextBlock) in un'etichetta, non è possibile collegare un evento del mouse direttamente nel controllo del bordo, infine è collegato in TextBlock, questa è la mia raccomandazione:

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

0

Penso che sia saggio usare una casella di testo senza bordi e sfondo come un modo semplice e veloce per raggiungere il blocco di testo allineato al centro

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>

-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>

1
La domanda era per un TextBlock, no TextBox. -1
KnorxThieus
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.