拼写检查不适用于 WPF 富文本框
本文关键字:文本 WPF 适用于 检查 不适用 | 更新日期: 2023-09-27 18:32:39
我正在尝试在WPF RichTextBox中启用拼写检查。MSDN 写道,System.Windows.Controls.SpellCheck 可用于启用 TextBox 和 RichTextBox 控件的拼写检查。
不幸的是,以下代码对我不起作用:
<RichTextBox SpellCheck.IsEnabled="True" xml:lang="en-US"></RichTextBox>
这很奇怪,因为如果我使用普通的文本框,它工作得很好(如果我拼写错误,我可以看到红线(。
不幸的是,到目前为止,我在SO上找到的每个答案都只提到将SpellCheck.IsEnabled
设置为True
并将Language
属性设置为支持的语言之一,但我不知道为什么这种方法在我的计算机上不起作用在内置RichTextBox的情况下?
更新:
如果我写这个,运行中的文本将带有下划线:
<RichTextBox SpellCheck.IsEnabled="True">
<FlowDocument Language="en">
<Paragraph>
<Run>asdfasdf</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
但不幸的是,如果我尝试输入其他文本,它将被忽略。看起来属性Language
未在编辑的内容上设置为英语。我甚至试图设置Thread's
CurrentCulture
和CurrentUICulture
都没有结果......
好的,终于我想出了这个问题的解决方案。如果您深入研究 WPF 源代码,则很容易看到问题:有一个名为 TextEditorTyping
的内部类,它有一个名为 DoTextInput
的方法,用于插入用户输入字符。此方法通过在TextEditor
上调用SetSelectedText
来设置插入区域的 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;
}
因此,该方法使用与Windows中当前输入语言相对应的InputLanguageManager.Current.CurrentInputLanguage
。如果使用的输入语言不同于英语(英语是 FrameworkElement.LanguageProperty 的默认值(,则如果编辑 RichText Box 中的文本,则 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)
{
...
// 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>
它会神奇地工作。:)