65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF 中支持拼写检查的富文本编辑器

starIconstarIconstarIconstarIconstarIcon

5.00/5 (6投票s)

2012年5月21日

CPOL

2分钟阅读

viewsIcon

49447

downloadIcon

1683

创建一个启用拼写检查的富文本编辑器。

字体选择

文本格式化

拼写检查

引言

在本文中,我将介绍如何在 WPF 中创建一个启用拼写检查的富文本编辑器。我的主要目标是以最快的速度,通过最少的步骤开发一个富文本编辑器,而无需深入研究 WPF 的极端复杂性。

背景

可以使用 RichTextBox 控件来创建富文本编辑器。RichTextBox 控件允许您处理文本、段落、图像、表格等内容。可以通过以下代码添加富文本框

<RichTextBox Margin="11,100,14,9" Name="richTextBox1"/>
添加拼写检查功能非常简单。您只需将 SpellCheck.IsEnabled 依赖属性设置为 true,如下所示
<RichTextBox Margin="11,100,14,9" Name="richTextBox1" SpellCheck.IsEnabled="True" />

RichTextBox 控件允许您使用 Document 对象来操作其内容。可以使用 RichTextBox 控件的 Document 属性来检索 Document 对象。

使用代码

以下 XAML 代码用于为工具栏图标创建位图资源

<Window.Resources>
    <BitmapImage x:Key="newicon" UriSource="new.png"/>
    <BitmapImage x:Key="openicon" UriSource="open.png"/>
    <BitmapImage x:Key="saveicon" UriSource="save.png"/>
    <BitmapImage x:Key="exiticon" UriSource="exit.png"/>
    <BitmapImage x:Key="undoicon" UriSource="undo.png"/>
    <BitmapImage x:Key="redoicon" UriSource="redo.png"/>
    <BitmapImage x:Key="selectallicon" UriSource="selectall.png"/>
    <BitmapImage x:Key="cuticon" UriSource="cut.png"/>
    <BitmapImage x:Key="copyicon" UriSource="copy.png"/>
    <BitmapImage x:Key="pasteicon" UriSource="paste.png"/>
    <BitmapImage x:Key="lefticon" UriSource="leftalign.png"/>
    <BitmapImage x:Key="centericon" UriSource="centeralign.png"/>
    <BitmapImage x:Key="righticon" UriSource="rightalign.png"/>
    <BitmapImage x:Key="boldicon" UriSource="bold.png"/>
    <BitmapImage x:Key="italicicon" UriSource="italic.png"/>
    <BitmapImage x:Key="underlineicon" UriSource="underline.png"/>
    <BitmapImage x:Key="increasefonticon" UriSource="increasefont.png"/>
    <BitmapImage x:Key="decreasefonticon" UriSource="decreasefont.png"/>
    <BitmapImage x:Key="abouticon" UriSource="about.png"/>
</Window.Resources>

以下代码创建一个 Grid 并将其 CommandBindings 添加到其 CommandBindings 集合

<Grid>
    <Grid.CommandBindings>
        <CommandBinding x:Name="newbinding" Command="ApplicationCommands.New" 
           CanExecute="newbinding_CanExecute" Executed="newbinding_Executed"/>
        <CommandBinding x:Name="openbinding" Command="ApplicationCommands.Open" 
           CanExecute="openbinding_CanExecute" Executed="openbinding_Executed"/>
        <CommandBinding x:Name="savebinding" Command="ApplicationCommands.Save" 
           CanExecute="savebinding_CanExecute" Executed="savebinding_Executed"/>
        <CommandBinding x:Name="exitbinding" Command="local:CustomCommands.Exit" 
           CanExecute="exitbinding_CanExecute" Executed="exitbinding_Executed"/>

在上面的代码中,CommandBindingCommand 属性指定命令为“新建”、“打开”、“保存”和“退出”。CanExecute 事件确定是否可以在指定的命令目标上执行该命令。Executed 事件指定在执行命令时应发生的操作。

值得注意的是,ApplicationCommands 类中没有“退出”命令。作为一种解决方法,我们可以创建一个自定义的“退出”命令,如下所示

public static class CustomCommands
{
    static CustomCommands()
    {
        exitCommand = new RoutedCommand("Exit", typeof(CustomCommands));
    }
    public static RoutedCommand Exit
    {
        get
        {
            return (exitCommand);
        }
    }
    static RoutedCommand exitCommand;
}

要使用我们自定义的退出命令,我们在窗口中添加以下引用

xmlns:local="clr-namespace:RichTextPad"

以下是我们的命令的代码

private void newbinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true; // Allow the command to execute.
}

private void newbinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
    TextRange range = new TextRange(richTextBox1.Document.ContentStart, 
        richTextBox1.Document.ContentEnd); // Get RichTextBox content.
    range.Text = "";    // Clear RichTextBox content.
    this.Title = "Untitled";
}

private void openbinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

private void openbinding_Executed(object sender, ExecutedRoutedEventArgs e)
// Code to open existing RTF file.
{
    try
    {
        FileDialog dialog = new OpenFileDialog();
        dialog.Filter = "RTF Files (*.rtf)|*.rtf|All Files(*.*)|*.*";
        dialog.FilterIndex = 1;
        if (dialog.ShowDialog() == true)
        {
            TextRange range = new TextRange(richTextBox1.Document.ContentStart, 
                                  richTextBox1.Document.ContentEnd);
            FileStream stream = new FileStream(dialog.FileName, FileMode.Open, 
                                    FileAccess.Read, FileShare.None);
            range.Load(stream, DataFormats.Rtf);
            stream.Close();
            this.Title = dialog.FileName;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

private void savebinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

private void savebinding_Executed(object sender, ExecutedRoutedEventArgs e)
// Code to save the current file.
{
    try
    {
        FileDialog dialog = new SaveFileDialog();
        dialog.Filter = "RTF Files (*.rtf)|*.rtf|All Files(*.*)|*.*";
        dialog.FilterIndex = 1;
        if (dialog.ShowDialog() == true)
        {
            TextRange range = new TextRange(richTextBox1.Document.ContentStart, 
                                            richTextBox1.Document.ContentEnd);
            FileStream stream = new FileStream(dialog.FileName, FileMode.Create, 
                                               FileAccess.Write, FileShare.None);
            range.Save(stream, DataFormats.Rtf);
            stream.Close();
            this.Title = dialog.FileName;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

private void exitbinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

private void exitbinding_Executed(object sender, ExecutedRoutedEventArgs e)
// Code to exit from the application
{
    Application.Current.Shutdown();
}

在上面的函数中,我使用 TextRange 类来获取 RichTextBox 内容并流式输入/输出以打开/保存文件。

以下预定义的命令可用于实现 RichTextBox 控件上的各种文本编辑操作。

<CommandBinding x:Name="undobinding" Command="ApplicationCommands.Undo"/>
<CommandBinding x:Name="redobinding" Command="ApplicationCommands.Redo"/>
<CommandBinding x:Name="selectallbinding" Command="ApplicationCommands.SelectAll"/>
<CommandBinding x:Name="cutbinding" Command="ApplicationCommands.Cut"/>
<CommandBinding x:Name="copybinding" Command="ApplicationCommands.Copy"/>
<CommandBinding x:Name="pastebinding" Command="ApplicationCommands.Paste"/>
<CommandBinding x:Name="leftalignbinding" Command="EditingCommands.AlignLeft"/>
<CommandBinding x:Name="centeralignbinding" Command="EditingCommands.AlignCenter"/>
<CommandBinding x:Name="rightalignbinding" Command="EditingCommands.AlignRight"/>
<CommandBinding x:Name="boldbinding" Command="EditingCommands.ToggleBold"/>
<CommandBinding x:Name="italicbinding" Command="EditingCommands.ToggleItalic"/>
<CommandBinding x:Name="underlinebinding" Command="EditingCommands.ToggleUnderline"/>
<CommandBinding x:Name="increasefontbinding" Command="EditingCommands.IncreaseFontSize"/>
<CommandBinding x:Name="decreasefontbinding" Command="EditingCommands.DecreaseFontSize"/>

以下代码创建工具栏按钮以执行命令

<ToolBarTray Background="White">
    <ToolBar Band="1" BandIndex="1" Height="50">
        <Button CommandTarget="{Binding richTextBox1}" Command="ApplicationCommands.New" ToolTip="New">
            <Image Source="{StaticResource newicon}"/>
        </Button>
        <Button CommandTarget="{Binding richTextBox1}" Command="ApplicationCommands.Open" ToolTip="Open">
            <Image Source="{StaticResource openicon}"/>
        </Button>
        <Button CommandTarget="{Binding richTextBox1}" Command="ApplicationCommands.Save" ToolTip="Save">
            <Image Source="{StaticResource saveicon}"/>
        </Button>
        <Button CommandTarget="{Binding richTextBox1}" Command="local:CustomCommands.Exit" ToolTip="Exit">
            <Image Source="{StaticResource exiticon}"/>
        </Button>
    </ToolBar>
    <ToolBar Band="1" BandIndex="2" Height="50">
        <Button Command="ApplicationCommands.Undo" ToolTip="Undo">
            <Image Source="{StaticResource undoicon}"/>
        </Button>
        <Button Command="ApplicationCommands.Redo" ToolTip="Redo">
            <Image Source="{StaticResource redoicon}"/>
        </Button>
    </ToolBar>
    <ToolBar Band="1" BandIndex="3" Height="50">
        <Button Command="ApplicationCommands.SelectAll" ToolTip="Select All">
            <Image Source="{StaticResource selectallicon}"/>
        </Button>
        <Button Command="ApplicationCommands.Cut" ToolTip="Cut">
            <Image Source="{StaticResource cuticon}"/>
        </Button>
        <Button Command="ApplicationCommands.Copy" ToolTip="Copy">
            <Image Source="{StaticResource copyicon}"/>
        </Button>
        <Button Command="ApplicationCommands.Paste" ToolTip="Paste">
            <Image Source="{StaticResource pasteicon}"/>
        </Button>
    </ToolBar>
    <ToolBar Band="1" BandIndex="4" Height="50">
        <Button Command="EditingCommands.AlignLeft" ToolTip="Align Left">
            <Image Source="{StaticResource lefticon}"/>
        </Button>
        <Button Command="EditingCommands.AlignCenter" ToolTip="Align Center">
            <Image Source="{StaticResource centericon}"/>
        </Button>
        <Button Command="EditingCommands.AlignRight" ToolTip="Align Right">
            <Image Source="{StaticResource righticon}"/>
        </Button>
    </ToolBar>
    <ToolBar Band="2" BandIndex="1" Height="50">
        <Button Command="EditingCommands.ToggleBold" ToolTip="Bold">
            <Image Source="{StaticResource boldicon}"/>
        </Button>
        <Button Command="EditingCommands.ToggleItalic" ToolTip="Italic">
            <Image Source="{StaticResource italicicon}"/>
        </Button>
        <Button Command="EditingCommands.ToggleUnderline" ToolTip="Underline">
            <Image Source="{StaticResource underlineicon}"/>
        </Button>
    </ToolBar>
    <ToolBar Band="2" BandIndex="2" Height="50">
        <ComboBox Name="cbFonts" ItemsSource="{x:Static Fonts.SystemFontFamilies}" 
                   SelectedIndex="0" ToolTip="Font">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" FontFamily="{Binding}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>
        <Button Command="EditingCommands.IncreaseFontSize" ToolTip="Increase Font Size">
            <Image Source="{StaticResource increasefonticon}"/>
        </Button>
        <Button Command="EditingCommands.DecreaseFontSize" ToolTip="Decrease Font Size">
            <Image Source="{StaticResource decreasefonticon}"/>
        </Button>
    </ToolBar>
    <ToolBar Band="2" BandIndex="3" Height="50">
        <ext:ColorPicker Name="colorChooser" 
           SelectedColorChanged="colorChooser_SelectedColorChanged" ToolTip="Text Color"/>
    </ToolBar>
    <ToolBar Band="2" BandIndex="4" Height="50">
        <Button Name="btnAbout" ToolTip="About RichTextPad" Click="btnAbout_Click">
            <Image Source="{StaticResource abouticon}"/>
        </Button>
    </ToolBar>
</ToolBarTray>

以下代码用于在选定的文本上设置字体

void cbFonts_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    TextRange range = new TextRange(richTextBox1.Selection.Start, 
        richTextBox1.Selection.End);    // Get RichTextBox content.
    range.ApplyPropertyValue(RichTextBox.FontFamilyProperty, 
        cbFonts.SelectedValue);    // Set the font selected from ComboBox on the RichTextBox
}

由于 WPF 中没有颜色选择对话框,我使用了 Extended WPF Toolkit 中的颜色选择器。将 Extended WPF Toolkit 库的引用添加到项目,并添加以下命名空间

xmlns:ext="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"

颜色选择器控件的添加方式如下

<ext:ColorPicker Name="colorChooser" 
   SelectedColorChanged="colorChooser_SelectedColorChanged" ToolTip="Text Color"/>

以下代码用于在选定的文本上设置颜色

private void colorChooser_SelectedColorChanged(object sender, RoutedPropertyChangedEventArgs<color> e)
{
    // Get RichTextBox content.
    TextRange range = new TextRange(richTextBox1.Selection.Start, richTextBox1.Selection.End);
    range.ApplyPropertyValue(RichTextBox.ForegroundProperty, 
          new SolidColorBrush(colorChooser.SelectedColor));
          // Apply the selected color.
}</color>

关注点

WPF 提供了一个丰富的编程模型来操作 RichTextBox。一旦我开始从事这个项目,我就意识到 WPF RichTextBox 控件的许多功能。我希望我的文章能帮助读者在短时间内理解这些概念。

© . All rights reserved.