การจัดแนวข้อความใน WPF TextBlock


228

ฉันจะกำหนดการจัดแนวกึ่งกลางแนวตั้งให้กับข้อความภายใน TextBlock ได้อย่างไร ฉันพบคุณสมบัติ TextAlignment แต่สำหรับการจัดแนวข้อความแนวนอน ฉันจะจัดแนวข้อความในแนวตั้งได้อย่างไร


@shr และอื่น ๆ : โปรดทราบว่าTextAlignmentมีผลกับการจัดตำแหน่งแนวนอนเท่านั้นไม่ใช่การจัดตำแหน่งแนวตั้ง (ตามที่คำถามหมายถึง)
Drew Noakes

คำตอบ:


284

บล็อกข้อความเองไม่สามารถจัดแนวตั้งได้

วิธีที่ดีที่สุดในการทำสิ่งนี้ที่ฉันได้พบคือการวาง textblock ไว้ในเส้นขอบดังนั้นเส้นขอบจึงจัดตำแหน่งให้คุณ

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

หมายเหตุ: ฟังก์ชันนี้เทียบเท่ากับการใช้กริดเพียงแค่ขึ้นอยู่กับว่าคุณต้องการให้ตัวควบคุมเข้ากับส่วนที่เหลือของเค้าโครงอย่างไร


22
+1 ความสูงของเส้นขอบต้องถูกตั้งค่าเพื่อให้การจัดตำแหน่งแนวตั้งมีผล
ทิมลอยด์

21
นอกจากนี้ TextBlock ไม่สามารถระบุความสูงได้มิเช่นนั้นจะไม่อยู่กึ่งกลางแนวตั้ง
pearcewg

20
@gav - การจัดแนวข้อความเท่านั้นจะจัดแนวนอนเท่านั้น ... คำถามเกี่ยวกับการจัดตำแหน่งแนวตั้ง
Orion Edwards

@TimLloyd - ฉันไม่แน่ใจว่าจริงเสมอ ฉันได้รับการตั้งค่านี้ชายแดนมีความสูง "อัตโนมัติ" และใช้งานได้ดี มันอยู่ในเซลล์กริดที่มีความสูงแถวติดดาว (และสิ่งอื่น ๆ ในแถว)
Bob Sammers

97

ในขณะที่Orion Edwards Answerทำงานได้ในทุกสถานการณ์อาจเป็นความเจ็บปวดในการเพิ่มเส้นขอบและกำหนดคุณสมบัติของเส้นขอบทุกครั้งที่คุณต้องการทำเช่นนี้ อีกวิธีที่รวดเร็วคือการตั้งค่าการขยายของบล็อคข้อความ:

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

11
ฉันคิดว่านี่เป็นคำตอบที่ยอดเยี่ยมที่สุด
Boppity Bop

1
ใช้งานได้เฉพาะถ้าแบบอักษรมีขนาด 16px ไม่ได้เท่านั้น!
C4d

1
คำตอบที่ได้รับการยอมรับจะจัดแนวเส้นขอบที่แท้จริงของกล่องข้อความในแนวตั้งอย่างถูกต้อง แต่ดูเหมือนจะไม่มีผลกับข้อความจริงภายใน ... ซึ่งฉันค่อนข้างแน่ใจว่าเป็นเจตนาของ OP วิธีการแก้ปัญหานี้ทำงานแทนคุณสมบัติ TextVerticalAlignment ที่เหมาะสมและได้รับ upvote ของฉัน :)
Trekkie

สิ่งที่เกี่ยวกับเนื้อหาแบบไดนามิกภายในบล็อกจะไม่ 2 หรือ 5 บรรทัดต้องใช้ช่องว่างภายในที่แตกต่างกันรวมถึงแบบอักษร 10pt vs 24pt
Reahreic

57

TextBlock ไม่รองรับการจัดตำแหน่งข้อความแนวตั้ง

ฉันแก้ไขสิ่งนี้ด้วยการตัดบล็อคข้อความด้วย Grid และตั้งค่า HorizontalAlignment = "Stretch" และ VerticalAlignment = "Center"

แบบนี้:

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

+1 ไม่จำเป็นต้องตั้งค่าความสูงสำหรับกริดเช่นเดียวกับวิธีการตามชายแดน
Efran Cobisi

ฉันพบว่าวิธีนี้ใช้ได้ผลดีที่สุดสำหรับฉัน ฉันสร้างไฟแสดงสถานะแบบไดนามิกโดยซ้อนทับTextBlockบนภายในEllipse Gridไม่จำเป็นต้องผูกคุณสมบัติความกว้างและความสูงของฉันหรือทำอะไรที่ยุ่งยาก
ข้าวเปลือก

17

คุณสามารถใช้ป้ายกำกับแทนการบล็อกข้อความ

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

3
นิสัยดีฉลากมี VerticalContentAlignment Greeeat +1
Ignacio Soler Garcia

3
ไม่ชัดเจนหาก OP จำเป็นต้องใช้ TextBlock หรืออาจติดป้ายกำกับ การใช้ป้ายกำกับนั้นทำงานตามที่ฉันต้องการ 1
สตีฟ Kalemkiewicz

19
วิธีนี้จะตอบคำถามวิธีสร้างข้อความแนวตั้งไม่ใช่วิธีการจัดแนวตั้ง!
Sebastian Negraszus

26
คำถามนี้กำลังถูกกล่าวถึงใน meta: meta.stackoverflow.com/questions/305572//
NathanOliver

6

หากคุณสามารถทำได้โดยไม่ใช้การตัดข้อความฉันคิดว่าการแทนที่ TextBlock ด้วย Label นั้นเป็นวิธีที่สั้นที่สุดในการทำเช่นนี้ มิฉะนั้นให้ทำตามคำตอบที่ถูกต้องข้อใดข้อหนึ่ง

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

6

TextBlockไม่รองรับการจัดแนวเนื้อหาของมัน หากคุณต้องใช้TextBlockคุณจะต้องจัดตำแหน่งให้สอดคล้องกับแม่ของมัน

อย่างไรก็ตามหากคุณสามารถใช้Labelแทน (และพวกเขามีฟังก์ชั่นที่คล้ายกันมาก) จากนั้นคุณสามารถจัดตำแหน่งเนื้อหาข้อความ:

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

ความLabelยืดจะเติมขอบเขตโดยค่าเริ่มต้นหมายถึงข้อความของป้ายจะอยู่กึ่งกลาง


3

สำหรับฉันVerticalAlignment="Center"แก้ไขปัญหานี้
อาจเป็นเพราะTextBlockมีการห่อในตาราง แต่ก็เป็นทุกอย่างใน wpf


1

ฉันพบว่าการปรับเปลี่ยนสไตล์กล่องข้อความ (เช่นcontroltemplate:) จากนั้นการแก้ไขการPART_ContentHostจัดตำแหน่งแนวตั้งเป็น Center จะทำเคล็ดลับ


OP กำลังถามเกี่ยวกับ TextBlocks พวกเขาไม่มี ControlTemplates
Aneves

1

เพียงแค่หัวเราะคิกคักให้ XAML นี้หมุนวน มันไม่สมบูรณ์แบบเพราะไม่ใช่ 'การจัดตำแหน่ง' แต่ช่วยให้คุณสามารถปรับการจัดแนวข้อความภายในย่อหน้า

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

1

หากคุณสามารถมองข้ามความสูงของ TextBlock ได้จะเป็นการดีกว่าถ้าคุณใช้สิ่งนี้:

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

1

ในกรณีของฉันฉันทำสิ่งนี้เพื่อให้การTextBlockแสดงผลดีกว่า

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

เคล็ดลับในการทำให้ข้อความเพิ่มเติมจากด้านล่างคือการตั้งค่า

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

0

คุณสามารถดูโพสต์บล็อกของฉัน คุณสามารถกำหนดความสูงที่กำหนดเองของ Textblock จาก codebehind สำหรับการตั้งค่าความสูงที่กำหนดเองคุณจะต้องตั้งค่าไว้ภายในในขอบหรือสแต็คแผง

http://ciintelligence.blogspot.com/2011/02/wpf-textblock-vertical-alignment-with.html


0

ฉันพบว่าฉันต้องทำมันแตกต่างกันเล็กน้อย ปัญหาของฉันคือถ้าฉันเปลี่ยนขนาดตัวอักษรข้อความจะเลื่อนขึ้นในกล่องข้อความแทนที่จะอยู่ที่ด้านล่างพร้อมกับส่วนที่เหลือของกล่องข้อความในบรรทัด ด้วยการเปลี่ยนการจัดเรียงแนวตั้งจากบนลงล่างฉันสามารถเปลี่ยนแบบอักษรจากขนาด 20 เป็น 14 และด้านหลังโดยรักษาแรงโน้มถ่วงของข้อความไว้ที่ด้านล่างและทำให้สิ่งต่าง ๆ เรียบร้อย นี่คือวิธี:

ป้อนคำอธิบายรูปภาพที่นี่


0

กล่องข้อความบรรทัดเดียวในแนวตั้ง

หากต้องการขยายคำตอบของ @Orion Edwards นี่คือวิธีที่คุณทำอย่างเต็มที่จากการใช้โค้ด (ไม่มีชุดสไตล์) โดยทั่วไปสร้างคลาสแบบกำหนดเองที่สืบทอดมาจากเส้นขอบซึ่งมีการตั้งค่าลูกของมันเป็นกล่องข้อความ ตัวอย่างด้านล่างสมมติว่าคุณต้องการเพียงหนึ่งบรรทัดและเส้นขอบนั้นเป็นลูกของ Canvas นอกจากนี้สมมติว่าคุณจะต้องปรับคุณสมบัติ MaxLength ของกล่องข้อความตามความกว้างของเส้นขอบ ตัวอย่างด้านล่างนี้ยังตั้งค่าเคอร์เซอร์ของเส้นขอบเพื่อเลียนแบบกล่องข้อความด้วยการตั้งค่าเป็นประเภท 'IBeam' ตั้งค่าระยะขอบของ '3' เพื่อให้กล่องข้อความนั้นไม่ได้อยู่ในแนวเดียวกันกับด้านซ้ายของเส้นขอบ

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

ประเภท:

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

ฉันคิดว่าดีกว่าที่จะใช้ Label (หรือ TextBlock) ใน Label คุณไม่สามารถแนบเหตุการณ์ของเมาส์โดยตรงในการควบคุมเส้นขอบในที่สุดมันก็ถูกแนบใน TextBlock นี่คือคำแนะนำของฉัน:

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

0

ฉันคิดว่าควรใช้กล่องข้อความที่ไม่มีเส้นขอบและพื้นหลังเป็นวิธีที่ง่ายและรวดเร็วในการเข้าถึง textblock ที่ตรงกลาง

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.