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?

Mrówka
źródło
@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

Orion Edwards
źródło
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" />
Ben Jones
źródło
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>
hwiechers
źródło
+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>
Aneesh Daniel
źródło
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"/>
Mike Fuchs
źródło
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.

Drew Noakes
źródło
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.

użytkownik448777
źródło
1

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

JLuis Estrada
źródło
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>
Gusdor
źródło
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"/>
fa wildchild
źródło
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"
Brandon Gao
źródło
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

Dave S.
źródło
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;
        }
    }
}
Aaron
źródło
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>
acamro
źródło
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}"
/>
StudioX
źródło
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Bastianon Massimo
źródło
1
Pytanie dotyczyło TextBlocknie TextBox. -1
KnorxThieus