好的,最终我已经找到了解决问题的方法。如果你深入挖掘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);
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>
这个网站描述了同样的问题。
幸运的是,我们有一个解决方法。我们已经看到了DoTextInput
方法的源代码,并且在其中有一个using块:
IDisposable disposable = This.Selection.DeclareChangeBlock();
using (disposable)
{
...
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>
它会神奇地工作。:)