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?

Ameise
quelle
@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

Orion Edwards
quelle
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" />
Ben Jones
quelle
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>
hwiechers
quelle
+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>
Aneesh Daniel
quelle
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"/>
Mike Fuchs
quelle
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.

Drew Noakes
quelle
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.

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

JLuis Estrada
quelle
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>
Gusdor
quelle
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"/>
fa wildchild
quelle
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"
Brandon Gao
quelle
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

Dave S.
quelle
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;
        }
    }
}
Aaron
quelle
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>
acamro
quelle
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}"
/>
StudioX
quelle
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Bastianon Massimo
quelle
1
Die Frage war für ein TextBlock, nicht TextBox. -1
KnorxThieus