Alignement vertical du texte dans WPF TextBlock

228

Comment attribuer un alignement central vertical au texte à l'intérieur d'un TextBlock? J'ai trouvé la propriété TextAlignment mais c'est pour l'alignement horizontal du texte. Comment le faire pour l'alignement vertical du texte?

Fourmi
la source
@shr et autres: notez que cela TextAlignmentn'affecte que l'alignement horizontal, pas l' alignement vertical (comme la question fait référence).
Drew Noakes du

Réponses:

284

Un bloc de texte lui-même ne peut pas faire d'alignement vertical

La meilleure façon de le faire que j'ai trouvée est de mettre le bloc de texte à l'intérieur d'une bordure, afin que la bordure fasse l'alignement pour vous.

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

Remarque: Ceci est fonctionnellement équivalent à l'utilisation d'une grille, cela dépend simplement de la façon dont vous souhaitez que les contrôles s'intègrent avec le reste de votre mise en page pour savoir lequel est le plus approprié

Orion Edwards
la source
22
+1 La hauteur de la bordure doit être définie pour que l'alignement vertical prenne effet.
Tim Lloyd
21
En outre, le TextBlock ne peut pas avoir une hauteur spécifiée, ou il ne sera pas centré verticalement.
pearcewg
20
@gav - TextAlignment ne fait que l'alignement horizontal ... la question concerne l'alignement vertical
Orion Edwards
@TimLloyd - Je ne suis pas sûr que ce soit toujours vrai. J'ai cette configuration, la bordure a la hauteur "Auto" et ça marche bien. Il est dans une cellule de grille avec des hauteurs de ligne étoilées (et d'autres choses dans la ligne).
Bob Sammers
97

Bien que Orion Edwards Answer fonctionne pour n'importe quelle situation, il peut être difficile d'ajouter la bordure et de définir les propriétés de la bordure à chaque fois que vous voulez faire cela. Un autre moyen rapide consiste à définir le remplissage du bloc de texte:

<TextBlock Height="22" Padding="3" />
Ben Jones
la source
11
je pense que c'est la réponse la plus brillante.
Boppity Bop
1
Cela ne fonctionne que si la police a une taille de 16 pixels, n'est-ce pas?
C4d
1
La réponse acceptée alignera correctement verticalement les bordures réelles de la TextBox, mais elle ne semble pas avoir d'effet sur le texte réel à l'intérieur ... ce qui est à peu près sûr que l'intention de l'OP. Cette solution fonctionne à la place d'une propriété TextVerticalAlignment appropriée et obtient mon vote positif. :)
Trekkie
Qu'en est-il du contenu dynamique dans le bloc, 2 ou 5 lignes ne nécessiteraient-elles pas un remplissage différent, également des polices 10pt vs 24pt
Reahreic
57

Le TextBlock ne prend pas en charge l'alignement vertical du texte.

Je contourne cela en enveloppant le bloc de texte avec une grille et en définissant HorizontalAlignment = "Stretch" et VerticalAlignment = "Center".

Comme ça:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>
hwiechers
la source
+1 N'a même pas besoin de définir la hauteur de la grille, comme avec l'approche basée sur la bordure.
Efran Cobisi
J'ai trouvé que cette approche me convenait le mieux. Je crée des lumières indicateur de dynamique en superposant TextBlockà l' Ellipseintérieur d' un Grid. Pas besoin de lier mes propriétés de largeur et de hauteur ou de faire quelque chose de délicat.
paddy
17

Vous pouvez utiliser une étiquette au lieu d'un bloc de texte.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>
Aneesh Daniel
la source
3
Bien, le Label a VerticalContentAlignment. Greeeat. +1
Ignacio Soler Garcia
3
Pas clair si l'OP devait utiliser un TextBlock ou pouvait s'en tirer avec une étiquette. L'utilisation d'une étiquette a fonctionné pour ce dont j'avais besoin. +1
Steve Kalemkiewicz
19
Cela répond à la question de savoir comment produire du texte vertical, pas comment appliquer l'alignement vertical!
Sebastian Negraszus
26
Cette question est en cours de discussion sur meta: meta.stackoverflow.com/questions/305572/…
NathanOliver
6

Si vous pouvez vous passer de l' habillage du texte , je pense que remplacer le TextBlock par une étiquette est la façon la plus succincte de le faire. Sinon, suivez l'une des autres réponses valides.

<Label Content="Some Text" VerticalAlignment="Center"/>
Mike Fuchs
la source
6

TextBlockne prend pas en charge l'alignement vertical de son contenu. Si vous devez utiliserTextBlock vous devez l'aligner par rapport à son parent.

Cependant, si vous pouvez utiliser à la Labelplace (et ils ont des fonctionnalités très similaires), vous pouvez positionner le contenu du texte:

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

Le Labelva s'étirer pour remplir ses limites par défaut, ce qui signifie que le texte de l'étiquette sera centré.

Drew Noakes
la source
3

Pour moi, VerticalAlignment="Center"résout ce problème.
Cela peut être dû au fait que le TextBlockest enveloppé dans une grille, mais il en va de même pour pratiquement tout dans wpf.

user448777
la source
1

J'ai trouvé que modifier le style de la zone de texte (c'est-à-dire:) controltemplatepuis modifier l' PART_ContentHostalignement vertical sur Centre fera l'affaire

JLuis Estrada
la source
OP pose des questions sur TextBlocks. Ils n'ont pas de ControlTemplates.
ANeves
1

Juste pour rire, donnez à ce XAML un tourbillon. Ce n'est pas parfait car ce n'est pas un «alignement» mais il vous permet d'ajuster l'alignement du texte dans un paragraphe.

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

Si vous pouvez ignorer la hauteur de TextBlock, il est préférable d'utiliser ceci:

<TextBlock Height="{Binding}" Text="Your text"
TextWrapping="Wrap" VerticalAlignment="Center" Width="28"/>
fa wildchild
la source
1

Dans mon cas, j'ai fait cela pour rendre l' TextBlockaffichage plus agréable.

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

L'astuce pour rendre le texte plus bas est de définir

Margin="0,0,0,-5"
Brandon Gao
la source
0

J'ai trouvé que je devais le faire légèrement différent. Mon problème était que si je modifiais la taille de la police, le texte se déplacerait vers le haut dans la TextBox au lieu de rester en bas avec le reste des TextBox sur la ligne. En changeant l'alignement vert de haut en bas, j'ai pu changer la police par programme de la taille 20 à la taille 14 et arrière, en gardant la gravité du texte en bas et en gardant les choses propres. Voici comment:

entrez la description de l'image ici

Dave S.
la source
0

TextBox à ligne unique aligné verticalement.

Pour développer la réponse fournie par @Orion Edwards, voici comment vous feriez complètement à partir de code-behind (aucun style défini). Fondamentalement, créez une classe personnalisée qui hérite de Border dont le Child est défini sur TextBox. L'exemple ci-dessous suppose que vous ne voulez qu'une seule ligne et que la bordure est un enfant d'un canevas. Suppose également que vous auriez besoin d'ajuster la propriété MaxLength de TextBox en fonction de la largeur de la bordure. L'exemple ci-dessous définit également le curseur de la bordure pour imiter une zone de texte en le définissant sur le type «IBeam». Une marge de «3» est définie de sorte que le TextBox n'est pas absolument aligné à gauche de la bordure.

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

Classe:

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
la source
0

Je pense qu'il vaut mieux utiliser un Label (ou TextBlock) dans un Label, vous ne pouvez pas attacher un événement de souris directement dans le contrôle de bordure, enfin il est attaché dans le TextBlock, voici ma recommandation:

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

Je pense qu'il est sage d'utiliser une zone de texte sans bordure ni arrière-plan comme moyen facile et rapide d'atteindre un bloc de texte aligné au centre

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>
StudioX
la source
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Bastianon Massimo
la source
1
La question était pour un TextBlocknon TextBox. -1
KnorxThieus