Вертикальное выравнивание текста в WPF TextBlock

228

Как назначить вертикальное выравнивание по центру текста внутри TextBlock? Я нашел свойство TextAlignment, но оно для горизонтального выравнивания текста. Как мне сделать это для вертикального выравнивания текста?

Муравей
источник
@shr и другие: обратите внимание, что это TextAlignmentвлияет только на горизонтальное выравнивание, а не на вертикальное выравнивание (как относится к вопросу).
Дрю Ноакс

Ответы:

284

Сам текстблок не может сделать вертикальное выравнивание

Наилучший способ сделать это, как я обнаружил, - поместить текстовый блок внутри границы, чтобы граница выровнялась за вас.

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

Примечание: это функционально эквивалентно использованию сетки, это просто зависит от того, как вы хотите, чтобы элементы управления вписывались в остальную часть вашего макета, какой из них больше подходит

Орион Эдвардс
источник
22
+1 Высота границы должна быть установлена, чтобы вертикальное выравнивание вступило в силу.
Тим Ллойд
21
Кроме того, TextBlock не может иметь указанную высоту, или он не будет центрироваться вертикально.
Pearcewg
20
@gav - TextAlignment выполняет только горизонтальное выравнивание ... вопрос о вертикальном выравнивании
Orion Edwards
@TimLloyd - я не уверен, что это всегда так. У меня есть эта настройка, граница имеет высоту "Авто", и она работает нормально. Он находится в ячейке сетки со звездной высотой строки (и других элементов в строке).
Боб Сэммерс
97

Хотя Orion Edwards Answer подходит для любой ситуации, добавление границы и установка свойств границы может быть затруднительной каждый раз, когда вы хотите это сделать. Другой быстрый способ - установить отступ текстового блока:

<TextBlock Height="22" Padding="3" />
Бен Джонс
источник
11
Я думаю, что это самый блестящий ответ.
Боппи Боп
1
Это работает, только если шрифт имеет размер 16px, не так ли?
C4d
1
Принятый ответ будет правильно выровнять фактические границы TextBox по вертикали, но, похоже, он не повлияет на фактический текст внутри ... который, я уверен, является намерением ОП. Это решение работает вместо правильного свойства TextVerticalAlignment и получает мое одобрение. :)
Trekkie
А как насчет динамического содержимого в блоке, для 2 или 5 строк не требуется различное заполнение, а также шрифты
10pt
57

TextBlock не поддерживает вертикальное выравнивание текста.

Я работаю над этим, оборачивая текстовый блок сеткой и устанавливая HorizontalAlignment = "Stretch" и VerticalAlignment = "Center".

Как это:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>
hwiechers
источник
+1 Даже не нужно устанавливать высоту для сетки, как при подходе на основе границ.
Эфран Кобизи
Я обнаружил, что этот подход работает лучше всего для меня. Я создаю индикатор динамического света, накладывая TextBlockна EllipseВнутри Grid. Не нужно связывать мои свойства ширины и высоты или делать что-то хитрое.
падди
17

Вы можете использовать метку вместо текстового блока.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>
Аниш Даниэль
источник
3
Хорошо, у Метки есть VerticalContentAlignment. Greeeat. +1
Игнасио Солер Гарсия
3
Непонятно, нужно ли OP использовать TextBlock или можно было бы получить ярлык. Использование ярлыка сработало для того, что мне было нужно. +1
Стив Калемкевич
19
Это отвечает на вопрос, как создавать вертикальный текст, а не как применять вертикальное выравнивание!
Себастьян Неграсус,
26
Этот вопрос обсуждается на meta: meta.stackoverflow.com/questions/305572/…
NathanOliver
6

Если вы можете обойтись без переноса текста , я думаю, что замена TextBlock на Label - самый краткий способ сделать это. В противном случае следуйте одному из других действительных ответов.

<Label Content="Some Text" VerticalAlignment="Center"/>
Майк Фукс
источник
6

TextBlockне поддерживает вертикальное выравнивание его содержимого. Если вы должны использовать, TextBlockто вы должны выровнять его по отношению к его родителю.

Однако, если вы можете использовать Labelвместо этого (и они имеют очень похожую функциональность), то вы можете расположить текстовое содержимое:

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

По Labelумолчанию будет растягиваться, чтобы заполнить свои границы, то есть текст метки будет центрирован.

Дрю Ноакс
источник
3

Для меня VerticalAlignment="Center"исправляет эту проблему.
Это может быть связано с TextBlockтем, что объект обернут в сетку, но практически все в wpf.

user448777
источник
1

Я обнаружил, что изменение стиля текстового поля (то есть:), controltemplateа затем изменение PART_ContentHostвертикального выравнивания по центру сделает свое дело

JLuis Estrada
источник
ОП спрашивает о TextBlocks. У них нет шаблонов управления.
Ноябрь
1

Только ради хихиканья, приведите XAML в движение. Он не идеален, поскольку не является «выравниванием», но позволяет регулировать выравнивание текста в абзаце.

<TextBlock>
    <TextBlock BaselineOffset="30">One</TextBlock>
    <TextBlock BaselineOffset="20">Two</TextBlock>  
    <Run>Three</Run>            
    <Run BaselineAlignment="Subscript">Four</Run>   
</TextBlock>
Gusdor
источник
1

Если вы можете пропустить высоту TextBlock, лучше использовать это:

<TextBlock Height="{Binding}" Text="Your text"
TextWrapping="Wrap" VerticalAlignment="Center" Width="28"/>
fa wildchild
источник
1

В моем случае я сделал это, чтобы сделать TextBlockдисплей лучше.

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

Уловка, чтобы сделать текст дальше от дна, состоит в том, чтобы установить

Margin="0,0,0,-5"
Брэндон Гао
источник
0

Я обнаружил, что должен был сделать это немного по-другому. Моя проблема заключалась в том, что если бы я изменил размер шрифта, текст в TextBox переместился бы вверх, а не остался внизу с остальными текстовыми полями на линии. Изменяя выравнивание вершин сверху вниз, я смог программно изменить шрифт с размера 20 до размера 14 и обратно, сохраняя гравитацию текста снизу и поддерживая чистоту. Вот как:

введите описание изображения здесь

Дейв С.
источник
0

Выровненная по вертикали одна строка TextBox

Чтобы расширить ответ, предоставленный @Orion Edwards, это то, как вы бы поступили полностью из кода (без установленных стилей). В основном создайте пользовательский класс, который наследует от Border, для которого Child имеет значение TextBox. В приведенном ниже примере предполагается, что вам нужна только одна строка, а граница является дочерним элементом Canvas. Также предполагается, что вам необходимо настроить свойство MaxLength элемента TextBox на основе ширины границы. В приведенном ниже примере также устанавливается курсор на границе для имитации текстового поля, устанавливая для него тип «IBeam». Поле '3' устанавливается так, чтобы TextBox не был абсолютно выровнен по левому краю.

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

Класс:

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

Я думаю, что лучше использовать Label (или TextBlock) в Label, вы не можете прикрепить событие мыши непосредственно в элементе управления границей, наконец, оно присоединено в TextBlock, это мое рекомендация:

<Label 
    Height="32"
    VerticalContentAlignment="Center"
    HorizontalContentAlignment="Stretch"
    MouseLeftButtonUp="MenuItem_MouseLeftButtonUp">
    <TextBlock Padding="32 0 10 0">
        Label with click event
    </TextBlock>
</Label>
acamro
источник
0

Я думаю, что было бы разумно использовать текстовое поле без рамки и фона в качестве простого и быстрого способа достичь центрированного текстового блока

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>
StudioX
источник
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Бастиан Массимо
источник
1
Вопрос был за, а TextBlockне TextBox. -1
KnorxThieus