【问题标题】:Spell checking doesn't work with WPF RichTextBox拼写检查不适用于 WPF RichTextBox
【发布时间】:2013-09-24 12:48:10
【问题描述】:

我正在尝试在 WPF RichTextBox 中启用拼写检查。 MSDN 写道,System.Windows.Controls.SpellCheck 可用于启用 TextBox 和 RichTextBox 控件的拼写检查。

很遗憾,以下代码对我不起作用:

<RichTextBox SpellCheck.IsEnabled="True" xml:lang="en-US"></RichTextBox>

这很奇怪,因为如果我使用纯文本框,它工作得非常好(如果我拼错了什么,我可以看到红线)。

不幸的是,everyanswer 到目前为止,我只提到将SpellCheck.IsEnabled 设置为True 并将Language 属性设置为一种受支持的语言,但我不知道为什么如果内置 RichTextBoxes,此方法在我的计算机上不起作用吗?

更新:

如果我这样写,运行中的文本将带下划线:

<RichTextBox SpellCheck.IsEnabled="True">
    <FlowDocument Language="en">
         <Paragraph>
             <Run>asdfasdf</Run>
         </Paragraph>
    </FlowDocument>
</RichTextBox>

但不幸的是,如果我尝试输入其他文本,它将被忽略。看起来属性Language 没有在编辑的内容上设置为英文。我什至尝试设置 Thread's CurrentCulture 和 CurrentUICulture 都没有结果...

【问题讨论】:

  • 对我来说效果很好。
  • 你能给我一些关于你测试什么环境的提示吗?操作系统版本、.NET 框架版本等...
  • 这不是一个有效的 FlowDocument 并为我抛出一个语法错误。第一级元素必须从 Block 驱动,而 Run 则不需要。尝试一个有效的第一级元素,例如段落。
  • 是的,你是对的,我已经编辑了我的问题。将代码复制粘贴到 StackOverflow 帖子后,段落部分不知何故丢失了。

标签: c# wpf textbox richtextbox spell-checking


【解决方案1】:

好的,我终于找到了解决问题的方法。如果您深入研究 WPF 源代码,可以很容易地发现问题:有一个名为 TextEditorTyping 的内部类,它有一个名为 DoTextInput 的方法,负责插入用户输入字符。该方法通过在TextEditor 上调用SetSelectedText 来设置插入范围的区域性属性(TextEditor 是另一个为各种控件提供文本编辑服务的内部类,例如RichTextBox)。这是DoTextInput 方法的一部分:

IDisposable disposable = This.Selection.DeclareChangeBlock();
using (disposable)
{
    ITextSelection selection = This.Selection;
    if (!This.AllowOvertype || !This._OvertypeMode)
    {
         flag = false;
    }
    else
    {
         flag = str != "\t";
    }
    ((ITextRange)selection).ApplyTypingHeuristics(flag);
    // SETTING THE CULTURE ->
    This.SetSelectedText(str, InputLanguageManager.Current.CurrentInputLanguage);
    ITextPointer textPointer = This.Selection.End.CreatePointer(LogicalDirection.Backward);
    This.Selection.SetCaretToPosition(textPointer, LogicalDirection.Backward, true, true);
    undoCloseAction = UndoCloseAction.Commit;
}

所以方法是使用InputLanguageManager.Current.CurrentInputLanguage,它对应于Windows中的当前输入语言。如果您使用不同于英语的输入语言(这是FrameworkElement.LanguageProperty 的默认值),那么如果您在 RichTextBox 中编辑文本,FlowDocument 中插入的元素将使用当前输入语言作为其Language 属性.例如,如果您的输入语言是匈牙利语 (hu-hu),您的 FlowDocument 将如下所示:

<FlowDocument>
     <Paragraph>
         <Run xml:lang="hu-hu">asdfasdf</Run>
     </Paragraph>
</FlowDocument>

This site 描述了同样的问题。

幸运的是,有一个解决方法。 我们已经看到了DoTextInput方法的源码,里面有一个using块:

IDisposable disposable = This.Selection.DeclareChangeBlock();
using (disposable)
{
    ...
    // SETTING THE CULTURE ->
    This.SetSelectedText(str, InputLanguageManager.Current.CurrentInputLanguage);
    ...
}

这是一个更改块,它在最后一行被释放 - 在它被释放后,TextContainerChanged 事件被触发,我们可以通过覆盖 RichTextBox 的 OnTextChanged 方法来处理它:

protected override void OnTextChanged(TextChangedEventArgs e)
{
    var changeList = e.Changes.ToList();
    if (changeList.Count > 0)
    {
        foreach (var change in changeList)
        {
            TextPointer start = null;
            TextPointer end = null;
            if (change.AddedLength > 0)
            {
                start = this.Document.ContentStart.GetPositionAtOffset(change.Offset);
                end = this.Document.ContentStart.GetPositionAtOffset(change.Offset + change.AddedLength);
            }
            else
            {
                int startOffset = Math.Max(change.Offset - change.RemovedLength, 0);
                start = this.Document.ContentStart.GetPositionAtOffset(startOffset);
                end = this.Document.ContentStart.GetPositionAtOffset(change.Offset);
            }

            if (start != null && end != null)
            {
                var range = new TextRange(start, end);
                range.ApplyPropertyValue(FrameworkElement.LanguageProperty, Document.Language);
            }
        }
    }
    base.OnTextChanged(e);
}

在这里,我们将已编辑范围的语言重置为正确的值 - Document.Language。 在此解决方法之后,您可以使用 WPF 拼写检查 - 例如,在法语中:

<My:CultureIndependentRichTextBox xml:lang="fr-FR" SpellCheck.IsEnabled="True">
     <FlowDocument>
     </FlowDocument>
</My:CultureIndependentRichTextBox>

它会神奇地起作用。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多