拼写检查不适用于WPF RichTextBox

时间:2013-09-24 12:48:10

标签: c# wpf textbox richtextbox spell-checking

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

不幸的是,以下代码对我不起作用:

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

这很奇怪,因为如果我使用普通的TextBox,它的效果非常好(如果我错过拼写的话,我可以看到红线)。

不幸的是,我在SO上发现的every answer到目前为止只提到将SpellCheck.IsEnabled设置为True并将Language属性设置为支持的语言,但我不知道为什么在内置RichTextBox的情况下这个方法在我的计算机上不起作用?

更新

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

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

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

1 个答案:

答案 0 :(得分:5)

好的,最后我找到了问题的解决方案。如果深入研究WPF源代码,可以很容易地看到问题:有一个名为TextEditorTyping的内部类,它有一个名为DoTextInput的方法,它负责插入用户输入字符。此方法通过在SetSelectedText上调用TextEditor来设置插入范围的culture属性(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中的inserted元素将使用当前输入语言作为其{{ 1}}属性。例如,如果您的输入语言是匈牙利语(Language),您的FlowDocument将如下所示:

hu-hu

This site描述了同样的问题。

幸运的是,有一个解决方法。 我们已经看到了<FlowDocument> <Paragraph> <Run xml:lang="hu-hu">asdfasdf</Run> </Paragraph> </FlowDocument> 方法的来源,里面有一个使用块:

DoTextInput

这是一个更改块,它被放置在最后一行 - 在它被处置之后,IDisposable disposable = This.Selection.DeclareChangeBlock(); using (disposable) { ... // SETTING THE CULTURE -> This.SetSelectedText(str, InputLanguageManager.Current.CurrentInputLanguage); ... } 事件被触发,我们可以通过覆盖TextContainerChanged OnTextChanged方法来处理它:

RichTextBox

这里我们将编辑范围的语言重置为正确的值 - 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); } 。 解决方法之后,您可以使用WPF拼写检查 - 例如,使用法语:

Document.Language

它会神奇地起作用。 :)