TOC

This article has been localized into Vietnamese by the community.

Các điều khiển Rich Text:

Điều khiển RichTextBox

Cho đến bây giờ, ta mới xem qua những wrappers chỉ-đọc cho FlowDocument, mà WPF cũng có một điều khiển cho phép một FlowDocument chỉnh sửa được: Điều khiển RichTextBox.

Ta có thể thêm một RichTextBox trực tiếp vào cửa số mà không có nội dung gì - trong trường hợp đó, nó sẽ tự động tạo một thực thể FlowDocument mà ta sẽ được chỉnh sửa trên đó. Hoặc, ta có thể wrap thực thể FlowDocument với RichTextBox và từ đó điều khiển nội dung ban đầu. Nó sẽ trông như này:

<Window x:Class="WpfTutorialSamples.Rich_text_controls.RichTextBoxSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RichTextBoxSample" Height="200" Width="300">
    <Grid>
        <RichTextBox Margin="10">
            <FlowDocument>
                <Paragraph FontSize="36">Hello, world!</Paragraph>
                <Paragraph FontStyle="Italic" TextAlignment="Left" FontSize="14" Foreground="Gray">Thanks to the RichTextBox control, this FlowDocument is completely editable!</Paragraph>
            </FlowDocument>
        </RichTextBox>
    </Grid>
</Window>

Qua ví dụ này, ta có thể chỉnh sửa rich text ngay bây giờ. Tuy nhiên, vì nội dung đã không còn dưới dạng chỉ-đọc, chúng ta sẽ rất muốn xem làm thế nào để sửa đổi văn bản, và làm việc với selection. Chúng ta sẽ xem cách làm ngay sau đây.

Một phần thú vị nữa là làm việc với các chức năng format có thể - cách làm sẽ ở trong trong bài sau, khi chúng ta cài đặt một trình biên tập rich text tuy nhỏ mà có võ.

Làm việc với văn bản và selection

Bởi bản chất của RichTextBox là một FlowDocument, và vì định dạng rich text rõ ràng phức tạp hơn plain text, nên làm việc với văn bản và selection không dễ như làm việc với điều khiển WPF TextBox.

Ví dụ dưới sẽ cho ta thấy sức mạnh của điều khiển RichTextBox khi làm việc với văn bản và/hoặc selection:

<Window x:Class="WpfTutorialSamples.Rich_text_controls.RichTextBoxTextSelectionSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RichTextBoxTextSelectionSample" Height="300" Width="400">
    <DockPanel>
        <WrapPanel DockPanel.Dock="Top">
            <Button Name="btnGetText" Click="btnGetText_Click">Get text</Button>
            <Button Name="btnSetText" Click="btnSetText_Click">Set text</Button>
            <Button Name="btnGetSelectedText" Click="btnGetSelectedText_Click">Get sel. text</Button>
            <Button Name="btnSetSelectedText" Click="btnSetSelectedText_Click">Replace sel. text</Button>
        </WrapPanel>
        <TextBox DockPanel.Dock="Bottom" Name="txtStatus" />
        <RichTextBox Name="rtbEditor" SelectionChanged="rtbEditor_SelectionChanged">
            <FlowDocument>
                <Paragraph FontSize="36">Hello, world!</Paragraph>
                <Paragraph FontStyle="Italic" TextAlignment="Left" FontSize="14" Foreground="Gray">Thanks to the RichTextBox control, this FlowDocument is completely editable!</Paragraph>
            </FlowDocument>
        </RichTextBox>
    </DockPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;

namespace WpfTutorialSamples.Rich_text_controls
{
	public partial class RichTextBoxTextSelectionSample : Window
	{
		public RichTextBoxTextSelectionSample()
		{
			InitializeComponent();
		}

		private void btnGetText_Click(object sender, RoutedEventArgs e)
		{
			TextRange textRange = new TextRange(rtbEditor.Document.ContentStart, rtbEditor.Document.ContentEnd);
			MessageBox.Show(textRange.Text);
		}

		private void btnSetText_Click(object sender, RoutedEventArgs e)
		{
			TextRange textRange = new TextRange(rtbEditor.Document.ContentStart, rtbEditor.Document.ContentEnd);
			textRange.Text = "Another world, another text!";
		}

		private void btnGetSelectedText_Click(object sender, RoutedEventArgs e)
		{
			MessageBox.Show(rtbEditor.Selection.Text);
		}

		private void btnSetSelectedText_Click(object sender, RoutedEventArgs e)
		{
			rtbEditor.Selection.Text = "[Replaced text]";
		}

		private void rtbEditor_SelectionChanged(object sender, RoutedEventArgs e)
		{
			TextRange tempRange = new TextRange(rtbEditor.Document.ContentStart, rtbEditor.Selection.Start);
			txtStatus.Text = "Selection starts at character #" + tempRange.Text.Length + Environment.NewLine;
			txtStatus.Text += "Selection is " + rtbEditor.Selection.Text.Length + " character(s) long" + Environment.NewLine;
			txtStatus.Text += "Selected text: '" + rtbEditor.Selection.Text + "'";
		}
	}
}

Như bạn có thể thấy, hộp thoại trên có một dãy các nút, một RichTextBox và một TextBox ở dưới cùng, cho thấy trạng thái lựa chọn hiện tại. Mỗi nút trong bốn nút trên sẽ thực hiện thao tác get, set hoặc thay thế văn bản.

Trong Code-behind, ta xử lý bốn sự kiện nhấn nút, cùng với sự kiện SelectionChanged đối với RichTextBox, điều mà sẽ cho phép ta hiển thị các thông số của selection hiện tại.

Để ý rằng thay vì ta truy cập một thuộc tính văn bản trực tiếp từ RichTextBox như ta làm ở một TextBox bình thường, chúng ta lại đang sử dụng những đối tượng TextRange với các TextPointer từ RichTextBox để lấy văn bản từ điều khiển hoặc từ selection trong điều khiển. Đây là cách mà RichTextBox hoạt động; như đã nói trên, khác với một TextBox bình thường ở nhiều khía cạnh.

Giãn cách các đoạn văn bản

Một điều mà ta có thể chú ý khi làm việc với RichTextBox, đó là khi bạn bấm Enter để bắt đầu một đoạn mới, đoạn mới sẽ cách đoạn cũ một dòng trống. Dưới đây là ảnh minh hoạ; tôi đã nhập ba dòng văn bản, mỗi dòng chỉ được cách dòng trước đúng bằng một lần bấm Enter:

Đối với một trình biên tập văn bản làm việc với các đoạn, đây là hành vi bình thường; nhưng tuỳ thuộc vào bạn đang dùng RichTextBox như thế nào và ở đâu, có thể hành vi này sẽ gây khó hiểu đối với người dùng rằng tại sao một nút bấm Enter lại xuống dòng xa như vậy.

May mắn thay, lỗi này rất dễ xử lý. Giãn cách giữa các dòng lớn như này là bởi các đoạn mặc định có lề lớn hơn 0, vì vậy ta chỉ cần xử lý bằng cách thay đổi thuộc tính này sử dụng một style, như sau:

<Window x:Class="WpfTutorialSamples.Rich_text_controls.RichTextBoxParagraphSpacingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="RichTextBoxParagraphSpacingSample" Height="150" Width="300">
    <Grid>
        <RichTextBox Margin="10">
            <RichTextBox.Resources>
                <Style TargetType="{x:Type Paragraph}">
                    <Setter Property="Margin" Value="0" />
                </Style>
            </RichTextBox.Resources>
        </RichTextBox>
    </Grid>
</Window>

Giờ thì các dòng không còn giãn như trước nữa, và nếu bạn muốn, bạn có thể đặt style ở trong cửa sổ hay kể cả trong App.xaml, nếu bạn muốn nó được áp dụng trên nhiều hơn một RichTextBox.

Tổng kết

RichTextBox rất dễ sử dụng, có nhiều tính năng, và có thể dễ dàng được sử dụng nếu ta muốn có một trình biên tập rich text đủ chức năng. Trong bài sau, ta sẽ xem cách để làm điều đó. Nó sẽ cho ta biết những chủ đề quan trọng như cách nạp và lưu một văn bản từ một RichTextBox và cách áp định dạng của văn bản trong điều khiển.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!