Wyrównanie tekstu w pionie w WPF TextBlock


228

Jak przypisać pionowe wyrównanie do środka tekstu w TextBlock? Znalazłem właściwość TextAlignment, ale służy ona do poziomego wyrównania tekstu. Jak to zrobić, aby wyrównać tekst w pionie?


@shr i inni: pamiętaj, że TextAlignmentwpływa tylko na wyrównanie w poziomie, a nie w pionie (jak dotyczy pytania).
Drew Noakes,

Odpowiedzi:


284

Sam blok tekstowy nie może wykonywać wyrównania pionowego

Najlepszym sposobem na zrobienie tego, co znalazłem, jest umieszczenie bloku tekstu w ramce, aby ta ramka wyrównała się dla Ciebie.

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

Uwaga: Jest to funkcjonalnie równoważne z użyciem siatki, zależy to tylko od tego, jak chcesz, aby elementy sterujące pasowały do ​​reszty układu, co do tego, który jest bardziej odpowiedni


22
+1 Wysokość granicy musi być ustawiona, aby wyrównanie pionowe zaczęło obowiązywać.
Tim Lloyd,

21
Ponadto TextBlock nie może mieć określonej wysokości lub nie będzie wyśrodkowywany w pionie.
pearcewg

20
@gav - TextAlignment wykonuje tylko wyrównanie w poziomie ... pytanie dotyczy wyrównania w pionie
Orion Edwards

@TimLloyd - Nie jestem pewien, czy to zawsze prawda. Mam tę konfigurację, ramka ma wysokość „Auto” i działa dobrze. Jest w komórce siatki z wysokościami wierszy oznaczonymi gwiazdką (i innymi rzeczami w rzędzie).
Bob Sammers

97

Podczas gdy Orion Edwards Answer działa w każdej sytuacji, dodawanie ramki i ustawianie właściwości ramki za każdym razem może być uciążliwe. Innym szybkim sposobem jest ustawienie dopełnienia bloku tekstowego:

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

11
myślę, że to najbardziej błyskotliwa odpowiedź.
Boppity Bop

1
Działa to tylko wtedy, gdy czcionka ma rozmiar 16px, prawda !?
C4d

1
Zaakceptowana odpowiedź poprawnie wyrówna w pionie rzeczywiste ramki TextBox, ale nie wydaje się, aby miała wpływ na rzeczywisty tekst wewnątrz ... co jestem całkiem pewien, że intencja PO. To rozwiązanie działa zamiast właściwej właściwości TextVerticalAlignment i otrzymuje moją opinię. :)
Trekkie

Co z dynamiczną zawartością w bloku, czy 2 lub 5 wierszy nie wymagałoby innego wypełnienia, także czcionek 10pt vs 24pt
Reahreic

57

TextBlock nie obsługuje pionowego wyrównania tekstu.

Obejmuję ten problem, owijając blok tekstowy siatką i ustawiając HorizontalAlignment = „Stretch” i VerticalAlignment = „Center”.

Lubię to:

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

+1 Nie trzeba nawet ustawiać wysokości siatki, jak w przypadku podejścia opartego na granicy.
Efran Cobisi

Odkryłem, że takie podejście działa najlepiej dla mnie. Tworzę kontrolki dynamiczny przez nałożenie TextBlockna EllipseWewnątrz Grid. Nie muszę wiązać moich właściwości szerokości i wysokości ani robić nic trudnego.
paddy

17

Możesz użyć etykiety zamiast bloku tekstu.

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

3
Fajnie, etykieta ma VerticalContentAlignment. Greeeat. +1
Ignacio Soler Garcia

3
Nie jest jasne, czy OP potrzebował użyć TextBlocka, czy mógłby uciec od etykiety. Korzystanie z etykiety działało tak, jak potrzebowałem. +1
Steve Kalemkiewicz

19
To odpowiada na pytanie, jak utworzyć tekst pionowy, a nie jak zastosować wyrównanie pionowe!
Sebastian Negraszus

26
To pytanie jest omawiane na stronie meta: meta.stackoverflow.com/questions/305572/...
NathanOliver

6

Jeśli możesz obejść się bez zawijania tekstu , myślę, że zastąpienie TextBlock etykietą jest najbardziej zwięzłym sposobem na zrobienie tego. W przeciwnym razie postępuj zgodnie z jedną z pozostałych prawidłowych odpowiedzi.

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

6

TextBlocknie obsługuje pionowego wyrównania jego zawartości. Jeśli musisz użyć TextBlock, musisz wyrównać go względem jego rodzica.

Jeśli jednak możesz użyć Labelzamiast tego (i mają one bardzo podobną funkcjonalność), możesz ustawić treść tekstu:

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

LabelPotrwają do wypełnienia swoich granic domyślnie, czyli tekst etykieta zostanie wyśrodkowany.


3

Dla mnie VerticalAlignment="Center"rozwiązuje ten problem.
Może to być spowodowane tym, że TextBlockjest on zawinięty w siatkę, ale tak samo jest praktycznie z wpf.


1

Przekonałem się, że modyfikacja stylu pola tekstowego (tj .:), controltemplatea następnie modyfikacja PART_ContentHostwyrównania pionowego do środka, załatwi sprawę


OP pyta o TextBlocks. Nie mają ControlTemplates.
ANeves

1

Tylko na chichot, daj temu XAMLowi wir. Nie jest doskonały, ponieważ nie jest „wyrównaniem”, ale umożliwia dostosowanie wyrównania tekstu w akapicie.

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

1

Jeśli możesz przeoczyć wysokość TextBlock, lepiej jest użyć tego:

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

1

W moim przypadku zrobiłem to, aby TextBlockwyświetlacz był ładniejszy.

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

Sztuczka, aby tekst był dalej od dołu, polega na ustawieniu

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


0

Stwierdziłem, że muszę to zrobić nieco inaczej. Mój problem polegał na tym, że gdybym zmienił rozmiar czcionki, tekst przesuwałby się w TextBoxie zamiast pozostać na dole z resztą TextBoxów w linii. Zmieniając wyrównanie pionu z góry na dół mogłem programowo zmienić czcionkę z rozmiaru 20 na rozmiar 14 i odwrotnie, utrzymując grawitację tekstu na dole i utrzymując porządek. Oto jak:

wprowadź opis zdjęcia tutaj


0

Wyrównany pionowo pojedynczy wiersz TextBox.

Aby rozwinąć odpowiedź udzieloną przez @Orion Edwards, w ten sposób zrobiłbyś to w pełni od kodu (bez stylów). Zasadniczo utwórz niestandardową klasę, która dziedziczy z Border, której potomek jest ustawiony na TextBox. Poniższy przykład zakłada, że ​​chcesz tylko pojedynczą linię i że obramowanie jest dzieckiem płótna. Zakłada również, że musisz dostosować właściwość MaxLength TextBox w oparciu o szerokość ramki. Poniższy przykład ustawia również kursor ramki naśladujący pole tekstowe, ustawiając go na typ „IBeam”. Margines „3” jest ustawiony tak, że TextBox nie jest absolutnie wyrównany do lewej krawędzi.

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

Klasa:

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

Myślę, że lepiej jest użyć Label (lub TextBlock) do Label, nie można dołączyć zdarzenia myszy bezpośrednio do kontrolki granicy, w końcu jest ono dołączone do TextBlock, to moja zalecenie:

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

0

Myślę, że rozsądnie jest używać pola tekstowego bez obramowania i tła jako łatwego i szybkiego sposobu na dotarcie do wyrównanego bloku tekstu

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.