Text vertical alignment in WPF TextBlock
Asked Answered
A

17

270

How do I assign vertical center alignment to the text inside a TextBlock? I found TextAlignment property but it is for horizontal text alignment. How do I do it for vertical text alignment?

Applicative answered 29/9, 2009 at 10:6 Comment(1)
@shr and others : note that TextAlignment only affects horizontal alignment, not vertical alignment (as the question refers to).Mlle
M
332

A Textblock itself can't do vertical alignment

The best way to do this that I've found is to put the textblock inside a border, so the border does the alignment for you.

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

Note: This is functionally equivalent to using a grid, it just depends how you want the controls to fit in with the rest of your layout as to which one is more suitable

Marylandmarylee answered 13/4, 2010 at 23:20 Comment(5)
+1 The height of the border must be set for the vertical alignment to take effect.Latrice
Also, the TextBlock can't have a height specified, or it won't center vertically.Sakhuja
@gav - TextAlignment only does horizontal alignment... the question is about vertical alignmentMarylandmarylee
@TimLloyd - I'm not sure that's always true. I've got this set-up, the border has height "Auto" and it's working fine. It's in a grid cell with starred row heights (and other things in the row).Northeastward
This does not work. I suspect that it vertically aligns the text control in the centre rather than the text.Chap
S
118

While Orion Edwards Answer works for any situation, it may be a pain to add the border and set the properties of the border every time you want to do this. Another quick way is to set the padding of the text block:

<TextBlock Height="22" Padding="3" />
Stephanystephen answered 11/11, 2010 at 16:27 Comment(5)
i think this is most brilliant answer.Cajuput
This only works if the font has a size of 16px doesnt it!?Lehet
The accepted answer will correctly vertically align the actual borders of the TextBox, but it doesn't appear to have an effect on the actual text within... which I'm pretty sure is the OP's intent. This solution works in lieu of a proper TextVerticalAlignment property and gets my upvote. :)Rosanarosane
What about dynamic content within the block, wouldn't 2 or 5 lines require different padding, also 10pt vs 24pt fontsHatchery
This is probably the most straightforward solution for non-dynamically-sized textblocksAscent
A
69

The TextBlock doesn't support vertical text alignment.

I work around this by wrapping the text block with a Grid and setting HorizontalAlignment="Stretch" and VerticalAlignment="Center".

Like this:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>
Anaphase answered 28/10, 2009 at 5:39 Comment(2)
+1 Doesn't even need to set the Height for the Grid, as with the Border-based approach.Prediction
I found this approach works best for me. I am creating dynamic indicator lights by overlaying TextBlock on Ellipse inside a Grid. No need to bind my width and height properties or do anything tricky.Enactment
M
17

You can use label instead of textblock.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>
Marked answered 22/8, 2011 at 10:1 Comment(4)
Nice, the Label has VerticalContentAlignment. Greeeat. +1Araxes
Not clear if the OP needed to use a TextBlock or could get away with a Label. Using a Label worked for what I needed. +1Ranson
This answers the question how to produce vertical text, not how to apply vertical alignment!Brainwork
This question is being discussed on meta: meta.#306072Selfdelusion
M
12

TextBlock doesn't support vertical alignment of its content. If you must use TextBlock then you have to align it with respect to its parent.

However if you can use Label instead (and they do have very similar functionality) then you can position the text content:

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

The Label will stretch to fill its bounds by default, meaning the label's text will be centred.

Mlle answered 12/12, 2017 at 21:3 Comment(1)
For me the only reasonable solution for the Textblock issue. Thanks fors the hint!Camarilla
H
8

If you can do without the text wrapping, I think that replacing the TextBlock with a Label is the most succinct way to do this. Otherwise follow one of the other valid answers.

<Label Content="Some Text" VerticalAlignment="Center"/>
Hallel answered 13/12, 2016 at 16:56 Comment(0)
C
4

The best way to achieve what you're talking about here, is to create a label, which supports VerticalContentAlignment

Then, if you really need some of TextBlock properties which Label doesn't cover, like TextWrapping you can place a TextBlock inside your Label

The result meets both your needs, VerticalContentAlignment and TextWrapping

<Label
   VerticalContentAlignment="Center">
   <TextBlock
             TextWrapping="WrapWithOverflow">
             My text goes here!
   </TextBlock> 
<Label/>
Cardoza answered 27/9, 2022 at 12:18 Comment(0)
R
3

For me, VerticalAlignment="Center" fixes this problem.
This could be because the TextBlockis wrapped in a grid, but then so is practically everything in wpf.

Richter answered 15/9, 2010 at 19:11 Comment(0)
G
2

In my case, I did this to make the TextBlock display nicer.

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

The trick to make the text further from the bottom is to set

Margin="0,0,0,-5"
Gibberish answered 19/9, 2012 at 6:46 Comment(0)
P
1

I've found that modifying the textbox style (ie: controltemplate) and then modifying the PART_ContentHost vertical alignment to Center will do the trick

Pratfall answered 25/11, 2011 at 19:28 Comment(1)
OP is asking about TextBlocks. They don't have ControlTemplates.Monda
P
1

Just for giggles, give this XAML a whirl. It isn't perfect as it is not an 'alignment' but it allows you to adjust text alignment within a paragraph.

<TextBlock>
    <TextBlock BaselineOffset="30">One</TextBlock>
    <TextBlock BaselineOffset="20">Two</TextBlock>  
    <Run>Three</Run>            
    <Run BaselineAlignment="Subscript">Four</Run>   
</TextBlock>
Protium answered 18/7, 2012 at 10:46 Comment(0)
A
1

If you can overlook the height of TextBlock, it's better for you to use this:

<TextBlock Height="{Binding}" Text="Your text"
TextWrapping="Wrap" VerticalAlignment="Center" Width="28"/>
Acquire answered 7/8, 2012 at 15:30 Comment(0)
P
0

I found I had to do it slightly different. My problem was that if I changed the font size, the text would move up in the TextBox instead of stay on the bottom with the rest of TextBoxes on the line. By changing the vert alignment from top to bottom I was able to change the font programmatically from size 20 to size 14 & back, keeping text's gravity on the bottom and keeping things neat. Here's how:

enter image description here

Punctate answered 8/8, 2013 at 15:13 Comment(0)
S
0

Vertically aligned single line TextBox.

To expand on the answer provided by @Orion Edwards, this is how you would do fully from code-behind (no styles set). Basically create a custom class that inherits from Border which has its Child set to a TextBox. The example below assumes that you only want a single line and that the border is a child of a Canvas. Also assumes you would need to adjust the MaxLength property of the TextBox based on the width of the Border. The example below also sets the cursor of the Border to mimic a Textbox by setting it to the type 'IBeam'. A margin of '3' is set so that the TextBox isn't absolutely aligned to the left of the border.

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

Class:

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;
        }
    }
}
Sanjuanitasank answered 8/9, 2014 at 16:47 Comment(0)
P
0

I think is better to use a Label(or TextBlock) into a Label, you can't attach a mouse event directly in the border control, finally it is attached in the TextBlock, this is my recomendation:

<Label 
    Height="32"
    VerticalContentAlignment="Center"
    HorizontalContentAlignment="Stretch"
    MouseLeftButtonUp="MenuItem_MouseLeftButtonUp">
    <TextBlock Padding="32 0 10 0">
        Label with click event
    </TextBlock>
</Label>
Polacca answered 20/11, 2016 at 3:21 Comment(0)
I
0

I think it's wise to use a textbox with no border and background as an easy and fast way to reach center aligned textblock

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>
Ibnsina answered 11/12, 2019 at 6:50 Comment(0)
P
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Pico answered 16/12, 2016 at 17:11 Comment(1)
The question was for a TextBlock, not TextBox. -1Iconography

© 2022 - 2024 — McMap. All rights reserved.