Perataan vertikal teks di WPF TextBlock

228

Bagaimana cara menetapkan perataan tengah vertikal ke teks di dalam TextBlock? Saya menemukan properti TextAlignment tetapi untuk perataan teks horizontal. Bagaimana saya melakukannya untuk penyelarasan teks vertikal?

Semut
sumber
@shr dan lain-lain: perhatikan bahwa TextAlignmenthanya memengaruhi perataan horizontal, bukan perataan vertikal (seperti yang dimaksud pertanyaan).
Drew Noakes

Jawaban:

284

Textblock itu sendiri tidak dapat melakukan perataan vertikal

Cara terbaik untuk melakukan ini yang saya temukan adalah dengan meletakkan blok teks di dalam perbatasan, sehingga perbatasan melakukan penyelarasan untuk Anda.

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

Catatan: Ini secara fungsional setara dengan menggunakan kisi, hanya tergantung bagaimana Anda ingin kontrol cocok dengan sisa tata letak Anda yang mana yang lebih cocok

Orion Edwards
sumber
22
+1 Ketinggian batas harus ditetapkan agar perataan vertikal berlaku.
Tim Lloyd
21
Juga, TextBlock tidak dapat memiliki ketinggian yang ditentukan, atau itu tidak akan terpusat secara vertikal.
pearcewg
20
@gav - TextAlignment hanya melakukan perataan horizontal ... pertanyaannya adalah tentang perataan vertikal
Orion Edwards
@TimLloyd - Saya tidak yakin itu selalu benar. Saya memiliki pengaturan ini, perbatasan memiliki "Auto" tinggi dan berfungsi dengan baik. Itu di sel kotak dengan ketinggian baris berbintang (dan hal-hal lain di baris).
Bob Sammers
97

Sementara Orion Edwards Answer berfungsi untuk situasi apa pun, mungkin menyusahkan untuk menambahkan perbatasan dan mengatur properti perbatasan setiap kali Anda ingin melakukan ini. Cara cepat lainnya adalah dengan mengatur padding dari blok teks:

<TextBlock Height="22" Padding="3" />
Ben Jones
sumber
11
Saya pikir ini adalah jawaban yang paling cemerlang.
Boppity Bop
1
Ini hanya berfungsi jika font memiliki ukuran 16px bukan !?
C4d
1
Jawaban yang diterima akan secara benar menyejajarkan batas sebenarnya dari TextBox, tetapi tampaknya tidak berpengaruh pada teks aktual di dalam ... yang saya cukup yakin adalah maksud OP. Solusi ini berfungsi sebagai pengganti properti TextVerticalAlignment yang tepat dan mendapatkan upvote saya. :)
Trekkie
Bagaimana dengan konten dinamis dalam blok, bukankah 2 atau 5 baris memerlukan padding yang berbeda, juga font 10pt vs 24pt
Reahreic
57

TextBlock tidak mendukung perataan teks vertikal.

Saya mengatasi ini dengan membungkus blok teks dengan Grid dan pengaturan HorizontalAlignment = "Peregangan" dan VerticalAlignment = "Tengah".

Seperti ini:

<Grid>
    <TextBlock 
        HorizontalAlignment="Stretch"
        VerticalAlignment="Center"
        Text="Your text" />
</Grid>
penambang
sumber
+1 bahkan tidak perlu mengatur Tinggi untuk Kotak, seperti dengan pendekatan berbasis Perbatasan.
Efran Cobisi
Saya menemukan pendekatan ini bekerja paling baik untuk saya. Saya menciptakan lampu indikator dinamis dengan overlay TextBlockpada Ellipsedi dalam Grid. Tidak perlu mengikat properti lebar dan tinggi saya atau melakukan sesuatu yang rumit.
padi
17

Anda dapat menggunakan label alih-alih blokir teks.

<Label Content="Hello, World!">
    <Label.LayoutTransform>
        <RotateTransform Angle="270"/>
    </Label.LayoutTransform>
</Label>
Aneesh Daniel
sumber
3
Bagus, Labelnya memiliki VerticalContentAlignment. Selamat +1
Ignacio Soler Garcia
3
Tidak jelas apakah OP perlu menggunakan TextBlock atau bisa lolos dengan Label. Menggunakan Label berhasil untuk apa yang saya butuhkan. +1
Steve Kalemkiewicz
19
Ini menjawab pertanyaan bagaimana menghasilkan teks vertikal, bukan bagaimana menerapkan perataan vertikal!
Sebastian Negraszus
26
Pertanyaan ini sedang dibahas di meta: meta.stackoverflow.com/questions/305572/…
NathanOliver
6

Jika Anda bisa melakukannya tanpa pembungkus teks , saya pikir mengganti TextBlock dengan Label adalah cara yang paling ringkas untuk melakukan ini. Kalau tidak, ikuti salah satu jawaban valid lainnya.

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

TextBlocktidak mendukung perataan vertikal kontennya. Jika Anda harus menggunakan TextBlockmaka Anda harus menyelaraskannya dengan induknya.

Namun jika Anda dapat menggunakannya Label(dan mereka memiliki fungsi yang sangat mirip) maka Anda dapat memposisikan konten teks:

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

The Labelakan meregang untuk mengisi batas yang secara default, yang berarti teks label akan dipusatkan.

Drew Noakes
sumber
3

Bagi saya, VerticalAlignment="Center"perbaiki masalah ini.
Ini bisa jadi karena TextBlockdibungkus dengan kisi-kisi, tetapi kemudian praktis semua dalam wpf.

pengguna448777
sumber
1

Saya telah menemukan bahwa memodifikasi gaya kotak teks (yaitu:) controltemplatedan kemudian memodifikasi PART_ContentHostperataan vertikal ke Tengah akan melakukan trik

JLuis Estrada
sumber
OP bertanya tentang TextBlocks. Mereka tidak memiliki ControlTemplates.
ANeves
1

Hanya untuk cekikikan, berikan XAML ini pusaran. Itu tidak sempurna karena itu bukan 'perataan' tetapi memungkinkan Anda untuk menyesuaikan perataan teks dalam paragraf.

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

Jika Anda dapat mengabaikan ketinggian TextBlock, lebih baik bagi Anda untuk menggunakan ini:

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

Dalam kasus saya, saya melakukan ini untuk membuat TextBlocktampilan lebih bagus.

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

Trik untuk membuat teks lebih jauh dari bawah adalah dengan mengatur

Margin="0,0,0,-5"
Brandon Gao
sumber
0

Saya menemukan saya harus melakukannya sedikit berbeda. Masalah saya adalah bahwa jika saya mengubah ukuran font, teks akan naik di TextBox alih-alih tetap di bawah dengan sisa TextBox di telepon. Dengan mengubah perataan vertikal dari atas ke bawah, saya dapat mengubah font secara terprogram dari ukuran 20 ke ukuran 14 & kembali, menjaga gravitasi teks di bagian bawah dan menjaga semuanya tetap rapi. Begini caranya:

masukkan deskripsi gambar di sini

Dave S.
sumber
0

TextBox baris tunggal sejajar vertikal.

Untuk memperluas jawaban yang diberikan oleh @Orion Edwards, inilah yang akan Anda lakukan sepenuhnya dari kode-belakang (tidak ada gaya yang ditetapkan). Pada dasarnya membuat kelas khusus yang mewarisi dari Border yang memiliki Anak diatur ke TextBox. Contoh di bawah ini mengasumsikan bahwa Anda hanya ingin satu baris dan bahwa perbatasan adalah anak kanvas. Juga mengasumsikan Anda perlu menyesuaikan properti MaxLength dari TextBox berdasarkan lebar Border. Contoh di bawah ini juga menetapkan kursor Border untuk meniru Textbox dengan mengaturnya ke tipe 'IBeam'. Margin '3' diatur sehingga TextBox tidak sepenuhnya selaras ke kiri perbatasan.

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

Kelas:

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;
        }
    }
}
Harun
sumber
0

Saya pikir lebih baik menggunakan Label (atau TextBlock) ke dalam Label, Anda tidak bisa melampirkan acara mouse langsung di kontrol perbatasan, akhirnya terpasang di TextBlock, ini rekomendasi saya:

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

Saya pikir itu bijaksana untuk menggunakan kotak teks tanpa batas dan latar belakang sebagai cara mudah dan cepat untuk mencapai blok teks rata tengah

<TextBox
TextWrapping="Wrap"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="{x:Null}"
BorderBrush="{x:Null}"
/>
StudioX
sumber
-1
  <TextBox AcceptsReturn="True" 
           TextWrapping="Wrap"  
           VerticalContentAlignment="Top" >
  </TextBox>
Bastianon Massimo
sumber
1
Pertanyaannya adalah untuk TextBlock, bukan TextBox. -1
KnorxThieus