Vertikale Textausrichtung in WPF TextBlock


228

Wie ordne ich dem Text in einem TextBlock eine vertikale Mittenausrichtung zu? Ich habe die TextAlignment-Eigenschaft gefunden, aber sie dient zur horizontalen Textausrichtung. Wie mache ich das für die vertikale Textausrichtung?


@shr und andere: Beachten Sie, dass dies TextAlignmentnur die horizontale Ausrichtung beeinflusst, nicht die vertikale Ausrichtung (wie in der Frage angegeben).
Drew Noakes

Antworten:


284

Ein Textblock selbst kann keine vertikale Ausrichtung durchführen

Der beste Weg, dies zu tun, den ich gefunden habe, besteht darin, den Textblock innerhalb eines Rahmens zu platzieren, damit der Rand die Ausrichtung für Sie übernimmt.

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

Hinweis: Dies entspricht funktional der Verwendung eines Rasters. Es hängt nur davon ab, wie die Steuerelemente in den Rest Ihres Layouts passen sollen, welches besser geeignet ist


22
+1 Die Höhe des Rahmens muss eingestellt werden, damit die vertikale Ausrichtung wirksam wird.
Tim Lloyd

21
Außerdem kann für den TextBlock keine Höhe angegeben werden, oder er wird nicht vertikal zentriert.
Pearcewg

20
@gav - TextAlignment macht nur horizontale Ausrichtung ... die Frage ist über vertikale Ausrichtung
Orion Edwards

@ TimLloyd - Ich bin mir nicht sicher, ob das immer stimmt. Ich habe dieses Setup, der Rand hat die Höhe "Auto" und es funktioniert gut. Es befindet sich in einer Gitterzelle mit markierten Zeilenhöhen (und anderen Dingen in der Zeile).
Bob Sammers

97

Während Orion Edwards Answer in jeder Situation funktioniert, kann es schwierig sein, den Rahmen hinzuzufügen und die Eigenschaften des Rahmens jedes Mal festzulegen, wenn Sie dies tun möchten. Eine andere schnelle Möglichkeit besteht darin, den Abstand des Textblocks festzulegen:

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

11
Ich denke, das ist die brillanteste Antwort.
Boppity Bop

1
Dies funktioniert nur, wenn die Schrift eine Größe von 16px hat, nicht wahr?
C4d

1
Die akzeptierte Antwort richtet die tatsächlichen Ränder der TextBox korrekt vertikal aus, scheint jedoch keine Auswirkungen auf den tatsächlichen Text in ... zu haben. Ich bin mir ziemlich sicher, dass dies die Absicht des OP ist. Diese Lösung funktioniert anstelle einer richtigen TextVerticalAlignment-Eigenschaft und erhält meine positive Bewertung. :)
Trekkie

Was ist mit dynamischem Inhalt innerhalb des Blocks? Würden nicht 2 oder 5 Zeilen unterschiedliche Auffüllungen erfordern, auch 10pt vs 24pt Schriftarten
Reahreic

57

Der TextBlock unterstützt keine vertikale Textausrichtung.

Ich arbeite darum, indem ich den Textblock mit einem Raster umschließe und HorizontalAlignment = "Stretch" und VerticalAlignment = "Center" setze.

So was:

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

+1 Muss nicht einmal die Höhe für das Gitter festlegen, wie beim randbasierten Ansatz.
Efran Cobisi

Ich fand, dass dieser Ansatz für mich am besten funktioniert. Ich schaffe dynamische Anzeige leuchtet durch Überlagerung TextBlockauf Ellipseinnen ein Grid. Sie müssen meine Eigenschaften für Breite und Höhe nicht binden oder etwas Schwieriges tun.
Paddy

17

Sie können Label anstelle von Textblock verwenden.

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

3
Schön, das Label hat VerticalContentAlignment. Greeeat. +1
Ignacio Soler Garcia

3
Nicht klar, ob das OP einen TextBlock verwenden musste oder mit einem Label davonkommen konnte. Die Verwendung eines Etiketts funktionierte für das, was ich brauchte. +1
Steve Kalemkiewicz

19
Dies beantwortet die Frage, wie vertikaler Text erzeugt wird, nicht wie vertikale Ausrichtung angewendet wird!
Sebastian Negraszus

26
Diese Frage wird auf Meta diskutiert: meta.stackoverflow.com/questions/305572/…
NathanOliver

6

Wenn Sie auf das Umbrechen von Text verzichten können , ist das Ersetzen des TextBlocks durch ein Etikett meiner Meinung nach der prägnanteste Weg, dies zu tun. Andernfalls folgen Sie einer der anderen gültigen Antworten.

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

6

TextBlockunterstützt keine vertikale Ausrichtung des Inhalts. Wenn Sie verwenden müssenTextBlock Sie es in Bezug auf das übergeordnete Element ausrichten.

Wenn Sie jedoch Labelstattdessen verwenden können (und sie haben sehr ähnliche Funktionen), können Sie den Textinhalt positionieren:

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

Das Labelwird gedehnt, um seine Grenzen standardmäßig zu füllen, was bedeutet, dass der Text des Etiketts zentriert wird.


3

VerticalAlignment="Center"Behebt für mich dieses Problem.
Dies könnte daran liegen, dass das TextBlockin ein Raster eingeschlossen ist, aber dann ist praktisch alles in wpf.


1

Ich habe festgestellt, dass das Ändern des Textfeldstils (dh :) controltemplateund das anschließende Ändern der PART_ContentHostvertikalen Ausrichtung auf Mitte den Trick ausführt


OP fragt nach TextBlocks. Sie haben keine ControlTemplates.
ANeves

1

Geben Sie diesem XAML nur zum Kichern einen Wirbel. Es ist nicht perfekt, da es keine 'Ausrichtung' ist, aber Sie können die Textausrichtung innerhalb eines Absatzes anpassen.

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

1

Wenn Sie die Höhe von TextBlock übersehen können, sollten Sie Folgendes verwenden:

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

1

In meinem Fall habe ich dies getan, um das TextBlockDisplay schöner zu machen .

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

Der Trick, um den Text weiter von unten zu entfernen, besteht darin, ihn festzulegen

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


0

Ich stellte fest, dass ich es etwas anders machen musste. Mein Problem war, dass wenn ich die Schriftgröße änderte, der Text in der TextBox nach oben verschoben wurde, anstatt mit den restlichen TextBoxen in der Zeile unten zu bleiben. Durch Ändern der Vert-Ausrichtung von oben nach unten konnte ich die Schriftart programmgesteuert von Größe 20 auf Größe 14 und zurück ändern, wobei die Schwerkraft des Texts unten blieb und die Dinge ordentlich blieben. Hier ist wie:

Geben Sie hier die Bildbeschreibung ein


0

Vertikal ausgerichtete einzeilige Textbox.

Um die Antwort von @Orion Edwards zu erweitern, gehen Sie wie folgt vor: Code-Behind (keine Stile festgelegt). Erstellen Sie im Grunde eine benutzerdefinierte Klasse, die von Border erbt und deren untergeordnetes Element auf eine Textbox festgelegt ist. Im folgenden Beispiel wird davon ausgegangen, dass Sie nur eine einzelne Zeile möchten und dass der Rand ein untergeordnetes Element einer Leinwand ist. Es wird auch davon ausgegangen, dass Sie die MaxLength-Eigenschaft der TextBox basierend auf der Breite des Rahmens anpassen müssen. Im folgenden Beispiel wird auch der Cursor des Rahmens so eingestellt, dass er ein Textfeld nachahmt, indem er auf den Typ 'IBeam' gesetzt wird. Ein Rand von '3' wird festgelegt, damit die TextBox nicht absolut links vom Rand ausgerichtet ist.

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

Klasse:

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

Ich denke, es ist besser, ein Label (oder TextBlock) in ein Label zu verwenden. Sie können ein Mausereignis nicht direkt im Rahmensteuerelement anhängen. Schließlich wird es im TextBlock angehängt. Dies ist meine Empfehlung:

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

0

Ich denke, es ist ratsam, ein Textfeld ohne Rand und Hintergrund zu verwenden, um auf einfache und schnelle Weise zum mittig ausgerichteten Textblock zu gelangen

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

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

1
Die Frage war für ein TextBlock, nicht TextBox. -1
KnorxThieus
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.