کنترل TextBlock

در حقیقت TextBlock یک کنترل محسوب نمی‌شود زیرا از کلاس Control ارث بری نمی‌کند، اما از آنجایی که مانند سایر کنترل‌ها از آن استفاده می‌کنیم، برای راحتی به آن کنترل TextBlock می گوییم. کنترل TextBlock یکی از ساده‌ترین و پایه‌ای‌ترین کنترل‌ها در WPF محسوب می‌شود. این کنترل مانند کنترل Label به شما اجازه می‌دهد تا یک متن را بر روی صفحه نشان دهید. اما این کار را به روشی ساده‌تر و کم هزینه‌تر انجام می‌دهد.

معمولاً تصور می‌شود که از Label فقط می‌توانیم برای متن‌های کوتاه و یک خطی استفاده کنیم، اما شما در Label می‌توانید از تصاویر هم استفاده کنید، در حالی که TextBlock فقط قادر به نمایش یک متن است و برای رشته‌های چند خطی نیز بسیار مناسب است. در مورد کنترل Label در بخش‌های بعدی بیشتر صحبت خواهیم کرد. TextBlock و Label هر کدام مزایای خودشان را دارند و شما می‌توانید بسته به شرایط، از هر دو استفاده کنبد. حال به کد زیر توجه کنید:

 1: <Window x:Class="WindowDemo.MainWindow"
 2:         xmlns       ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3:         xmlns:x     ="http://schemas.microsoft.com/winfx/2006/xaml"
 4:         xmlns:d     ="http://schemas.microsoft.com/expression/blend/2008"
 5:         xmlns:mc    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6:         xmlns:local ="clr-namespace:WindowDemo"
 7:         mc:Ignorable="d"
 8:         Title="MainWindow" Height="200" Width="300">
 9:     <Grid>
10:         <TextBlock>This is a TextBlock</TextBlock>
11:     </Grid>
12: </Window>

در اینجا ما یک TextBlock را به پنجره خود اضافه کردیم (خط 10) و متن This is a TextBlock را داخل آن قرار دادیم. زمانی که برنامه را اجرا کنیم خروجی به شکل زیر خواهید بود:

حال یک متن طولانی‌تر را در داخل TextBlock می نویسیم:

<TextBlock>This is a TextBlock control and it comes with a very long text</TextBlock>

زمانی که برنامه را اجرا کنید خروجی زیر را برای شما نمایش می‌دهد:

همانطور که مشاهده می‌کنید، متن به صورت کامل نمایش داده نمی‌شود و بخشی از متن از کادر خارج می‌شود. هنگام نمایش یک متن طولانی، در صورتی که متن ما بزرگ از اندازه پنجره باشد، بخشی از آن نمایش داده نمی‌شود. خوشبختانه روش‌های مختلفی برای برطرف کردن این مشکل وجود دارد که در ادامه آن‌ها را بررسی می‌کنم. به کد زیر توجه کنید:

<StackPanel>

    <TextBlock Margin ="10" Foreground ="Red">
               This is a TextBlock control<LineBreak/>
               with multiple lines of text.
    </TextBlock>

    <TextBlock Margin ="10" Foreground ="Green" TextTrimming ="CharacterEllipsis">
               This is a TextBlock control with text that may not be rendered         
               completely, which will be indicated with an ellipsis.
    </TextBlock>

    <TextBlock Margin ="10" Foreground ="Blue" TextWrapping ="Wrap">
               This is a TextBlock control with automatically wrapped text,   
               using the TextWrapping property.
    </TextBlock>

</StackPanel>

زمانی که این برنامه را اجرا کنید خروجی زیر را مشاهده خواهید کرد:

در این مثال ما سه کنترل TextBlock داریم که هر کدام رنگ متفاوتی دارند. برای اختصاص رنگ به هر TextBlock از مشخصه Foreground استفاده کردیم. همچنین با استفاده از مشخصه Margin می‌توانیم یک فاصله را از چهار جهت برای هر متن در نظر بگیریم. برای مثال در اینجا Margin را برابر با 10 در نظر گرفتیم که یک فاصله 10 پیکسلی را از هر چهار جهت برای TextBlock ما در نظر می‌گیرد.

در TextBlock قرمز، متنی که بعد از تگ LineBreak قرار دارد، در خط بعدی نمایش داده می‌شود. به عبارت دیگر با استفاده از این تگ، می‌توانیم در متن خود Enter بزنیم. این روش انعطاف پذیری مناسبی ندارد و زمانی که کاربر اندازه پنجره را بزرگ‌تر یا کوچکتر کند، متن ما همچنان به همان شکل باقی می‌ماند.

در TextBlock سبز، از مشخصه TextTrimming با مقدار CharacterEllipsis استفاده کردیم که در این صورت هنگامی که متن ما بزرگتر از اندازه پنجره باشد، ادامه متن را با سه نقطه (…) نمایش می‌دهد. این روش زمانی مناسب است که متن شما طولانی باشد ولی نمی‌خواهید بیشتر از یک خط شود. اگر به جای CharacterEllipsis از WordEllipsis استفاده کنید، باز هم اگر متن شما بزرگتر از اندازه پنجره باشد، ادامه متن را با سه نقطه نمایش می‌دهد، اما با این تفاوت که آخرین کلمه را به صورت کامل نمایش می‌دهد. اگر به تصویر بالا توجه کنید، مشاهده می‌کنید که کلمه not به صورت ناقص ظاهر شده است زیرا از CharacterEllipsis استفاده کردیم. اما در صورتی که از مقدار WordEllipsis استفاده کنید، آخرین کلمه را به صورت کامل نمایش می‌دهد.

در TextBlock آبی، از مشخصه TextWrapping با مقدار Wrap استفاده کردیم که در این صورت هنگامی که متن ما بزرگتر از اندازه پنجره باشد، به صورت خودکار متن را در چند خط نمایش می‌دهد. اگر در مثال بالا اندازه پنجره را کوچک یا بزرگ کنید مشاهده خواهید کرد که متن ما متناسب با اندازه پنجره تنظیم می‌شود. همچنین شما می‌توانید مقدار WrapWithOverflow را نیز برای TextWrapping در نظر بگیرید. برای اینکه تفاوت این دو را به صورت دقیق درک کنید به مثال زیر توجه کنید:

<StackPanel>

    <TextBlock Margin ="10" Foreground ="Blue" TextWrapping ="Wrap">
               This is a test of the superduperbigwordcantreallywrapproperly.
    </TextBlock>

    <TextBlock Margin ="10" Foreground ="Red" TextWrapping ="WrapWithOverflow">
               This is a test of the superduperbigwordcantreallywrapproperly.
    </TextBlock>

</StackPanel>

در این مثال ما دو TextBlock به رنگ‌های قرمز و آبی داریم که یک متن یکسان و TextWrapping های متفاوت دارند. زمانی که این برنامه را اجرا کنیم خروجی زیر را به ما نشان می‌دهد:

در هر دو، زمانی که اندازه پنجره را تغییر دهیم، اگر متن بزرگتر از اندازه پنجره باشد، متن را متناسب با آن در چند خط نمایش می‌دهند. اما تفاوت زمانی است که در متن، یک کلمه طولانی داشته باشیم که از اندازه پنجره بزرگتر باشد.

در این مثال، متن “superduperbigwordcantreallywrapproperly” را یک کلمه حساب می‌کند زیرا بین حروف آن space وجود ندارد. حال اگر مقدار Wrap را برای TextWrapping در نظر بگیریم، زمانی که نتواند یک کلمه را در فضایی که در اختیار دارد نمایش دهد، کلمه را تکه تکه کرده و بخشی از آن را در خط بعد نمایش می‌دهد. اما زمانی که از WrapWithOverflow استفاده کنیم، اگر نتواند یک کلمه را در پنجره جا دهد، همانطور که از اسم آن هم مشخص است، Overflow می‌کند و کلمه را به صورت ناقص در صفحه نمایش می‌دهد.

تراز بندی متن در TextBlock

عمل ترازبندی با مرتب کردن لبه‌های متن، باعث افزایش خوانایی آن می‌شود. برای درک بهتر به مثال زیر توجه کنید:

<StackPanel>
    <TextBlock Margin="5" TextWrapping="Wrap" TextAlignment="Left   ">WPF allows justification of text.</TextBlock>
    <TextBlock Margin="5" TextWrapping="Wrap" TextAlignment="Right  ">WPF allows justification of text.</TextBlock>
    <TextBlock Margin="5" TextWrapping="Wrap" TextAlignment="Center ">WPF allows justification of text.</TextBlock>
    <TextBlock Margin="5" TextWrapping="Wrap" TextAlignment="Justify">
        WPF allows justification of text using the TextBlock element.
        You specify justification in a TextBlock using the TextAlignment property.
    </TextBlock>
</StackPanel>

زمانی که این برنامه را اجرا کنید خروجی زیر را برای شما نمایش می‌دهد:

در این برنامه تفاوت بین انواع روش‌های ترازبندی متن کاملاً مشخص است.

در این بخش، شما با روش کار کردن با متن‌های ساده را در TextBlock آشنا شدید. در ادامه در مورد قابلیت‌های پیشرفته‌تر این کنترل صحبت خواهید کرد.

 

فرمت بندی متن

کنترل TextBlock از محتوای Inline پیشتیبانی می‌کند که به این معنی است که شما می‌توانید بخشی از یک متن را فرمت بندی کنید. فرمت‌هایی که شما می‌توانید در متن خود استفاده کنید عبارتند از:

AnchoredBlock Hyperlink Bold
Underline Italic LineBreak
InlineUIContainer Run Span

تگ‌های Bold، Italic و Underline

این عناصر ساده‌ترین نوع فرمت بندی Inline هستند که نام آن‌ها نیز نحوه عملکردشان را نشان می‌دهد. به مثال زیر توجه کنید:

<TextBlock Margin ="10" TextWrapping ="Wrap">
           TextBlock with <Bold>bold</Bold>, <Italic>italic</Italic> and      
            <Underline>underlined</Underline> text.
</TextBlock>

خروجی کد بالا به صورت زیر است:

مشابه HTML، شما می‌توانید از تگ‌های Bold (برای برجسته کردن)، Italic (برای مورب کردن) و Underline (برای کشیدن خط زیر) استفاده کنید. همچنین این سه تگ را می‌توانید در داخل تگ Span که در ادامه بررسی می‌کنیم نیز استفاده کنید.

تگ LineBreak

همانطور که در بخش قبل نیز مشاهده کردید، با استفاده از این تگ می‌توانیم در متن خود Enter بزنیم. برای مثال به کد زیر توجه کنید:

<TextBlock Margin ="10"  TextWrapping ="Wrap">
           Line1<LineBreak/>
           Line2<LineBreak/>
           Line3<LineBreak/>
           .    <LineBreak/>
           .    <LineBreak/> 
           .    <LineBreak/>
           LineN
</TextBlock>

خروجی کد بالا به صورت زیر است:

تگ Hyperlink

با استفاده از این تگ می‌توانید یک لینک را در متن خود قرار دهید. نحوه نمایش این لینک متناسب با تم پنجره‌های شماست. معمولاً یک متن آبی رنگ با یک خط در زیر آن است که وقتی موس بر روی آن قرار می‌گیرد، رنگش به قرمز تغییر پیدا می‌کند و کرسر موس نیز به شکل در می‌آید. به مثال زیر توجه کنید:

<TextBlock Margin ="10" TextWrapping ="Wrap">
           This text has a <Hyperlink   
           RequestNavigate ="Hyperlink_RequestNavigate"  
           NavigateUri     ="https://www.google.com">link</Hyperlink> in it.
</TextBlock>

خروجی کد بالا به صورت زیر است:

در این مثال ما کلمه link را داخل تگ Hyperlink قرار دادیم و همچنین با استفاده از مشخصه NavigateUri یک آدرس را تعیین کردیم که در صورت کلیک شدن بر روی لینک، آن را برای ما نمایش دهد. اما برای باز کردن آدرس یک سایت، فقط نوشتن مشخصه NavigateUri کافی نیست و باید مشخصه RequestNavigate را نیز به Hyperlink اضافه کنیم. در مقابل RequestNavigate باید نام متدی را بنویسیم که در صورت کلیک شدن بر روی لینک، می‌خواهیم اجرا شود. ساختار کلی این متد به شکل زیر است:

private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
    System.Diagnostics.Process.Start(e.Uri.AbsoluteUri);
}

زمانی که بر روی لینک کلیک شود، این متد فراخوانی خواهد شد. در داخل این متد شما هر کدی که بخواهید می‌توانید بنویسید برای مثال باز کردن یک پنجره دیگر. اما در اینجا هدف ما باز کردن آدرس یک سایت است که با استفاده تابع Start از کلاس Process این کار را انجام می‌دهیم. برای اینکه در کدهای سی شارپ، به آدرسی که داخل مشخصه NavigateUri قرار دارد دسترسی پیدا کنیم از e.Uri.AbsoluteUri استفاده می‌کنیم.

تگ Span

با استفاده از این عنصر می‌توانید تغییرات مختلفی را بر روی متن خود اعمال کنید که برخی از آن‌ها عبارتند از: FontWeight ،FontStyle ،Background Foreground و … . ویژگی مهم Span این است که به شما اجازه می‌دهد تا دیگر عناصر Inline را نیز داخل آن به کار ببرید و به سادگی متن‌هایی با سبک‌های ترکیبی ایجاد کنید. به مثال زیر توجه کنید:

<TextBlock Margin ="10" TextWrapping  ="Wrap">
           This 
           <Span FontWeight     ="Bold">is</Span> a
           <Span Background     ="Silver" Foreground="Maroon">TextBlock</Span>
            with 
           <Span TextDecorations="Underline">several</Span>
           <Span FontStyle      ="Italic">Span</Span> elements,
           <Span Foreground     ="Blue">using a <Bold>variety</Bold> of <Italic>styles</Italic></Span>.
</TextBlock>

زمانی که این برنامه را اجرا کنید خروجی زیر را برای شما نشان می‌دهد:

در این مثال توانستیم انواع تگ‌ها و مشخصه‌های فرمت بندی متن را به صورت ترکیبی استفاده کنیم.

تگ Run

با استفاده از این تگ نیز می‌توانید یک یا چند style را به متن خود اعمال کنید. شما همچنین می‌توانید از تمام مشخصه‌هایی که در تگ Span وجود دارند نیز استفاده کنید اما با این تفاوت که در Span، شما می‌توانستید سایر مؤلفه‌های Inline را هم به کار ببرید، اما Run فقط می‌تواند شامل یک متن ساده باشد. به مثال زیر توجه کنید:

<TextBlock Margin ="10" TextWrapping ="Wrap  ">
    <Run FontWeight ="Bold">This is a Bold Text                                 </Run> <LineBreak/>
    <Run FontStyle  ="Italic">This is an Italic Text                            </Run> <LineBreak/>
    <Run FontWeight ="Bold" FontStyle="Italic">This is an Italic and  Bold Text </Run> <LineBreak/>
    <Run FontWeight ="Bold" Foreground="Red"  >This is a Bold and Red Text      </Run>
</TextBlock>

همانطور که در این مثال نیز مشخص است فقط می‌توانیم یک یا چند سبک را به متن خود اعمال کنیم، بنابراین انعطاف پذیری کمتری نسبت به Span در اختیار ما قرار می‌دهد:

فرمت بندی متن از طریق #C

همانطور که مشاهده کردید، فرمت بندی متن از طریق XAML کار بسیار ساده‌ای است. اما گاهی اوقات ممکن است ترجیح دهید یا اینکه مجبور باشید، فرمت بندی را از طریق کدهای سی شارپ انجام دهید. انجام این کار امکان پذیر است اما شاید کمی سخت باشد. به مثال زیر توجه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WindowDemo
{
    /// 
    /// Interaction logic for MainWindow.xaml
    /// 
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            TextBlock textblock = new TextBlock();
            textblock.TextWrapping = TextWrapping.Wrap;
            textblock.Margin = new Thickness(10);
            textblock.Inlines.Add("An example on ");
            textblock.Inlines.Add(new Run("the TextBlock control ") { FontWeight = FontWeights.Bold });
            textblock.Inlines.Add("using ");
            textblock.Inlines.Add(new Run("inline ") { FontStyle = FontStyles.Italic });
            textblock.Inlines.Add(new Run("text formatting ") { Foreground = Brushes.Blue });
            textblock.Inlines.Add("from ");
            textblock.Inlines.Add(new Run("Code-Behind") { TextDecorations = TextDecorations.Underline });
            textblock.Inlines.Add(".");
            this.Content = textblock;
        }
    }
}

زمانی که برنامه بالا را اجرا کنید خروجی زیر را برای شما نشان می‌دهد:

معادل کدهای سی شارپ بالا در xaml به صورت زیر می‌باشد:

<TextBlock Margin="10" TextWrapping="Wrap">
    An example on 
    <Run FontWeight="Bold">the TextBlock control</Run>
    using 
    <Run FontStyle="Italic">inline</Run>
    <Run Foreground="Blue">text formatting</Run>
    from 
    <Run TextDecorations="Underline">Code-Behind</Run>.
</TextBlock>