Zso*_*olt 3 c# wpf textbox spell-checking richtextbox
我正在尝试在WPF RichTextBox中启用拼写检查。MSDN写道System.Windows.Controls.SpellCheck可用于为TextBox和RichTextBox控件启用拼写检查。
不幸的是,以下代码对我不起作用:
<RichTextBox SpellCheck.IsEnabled="True" xml:lang="en-US"></RichTextBox>
Run Code Online (Sandbox Code Playgroud)
这很奇怪,因为如果我使用普通的TextBox,它可以很好地工作(如果我拼错了一些东西,我会看到红线)。
不幸的是,每一个 答案我已经在SO到目前为止只提及到一套发现SpellCheck.IsEnabled,以True和设置Language属性为所支持的语言之一,但我不知道为什么在的情况下,我的计算机上应用此方法不工作内置RichTextBoxes?
更新:
如果我这样写,则运行中的文本将带有下划线:
<RichTextBox SpellCheck.IsEnabled="True">
<FlowDocument Language="en">
<Paragraph>
<Run>asdfasdf</Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
Run Code Online (Sandbox Code Playgroud)
但是不幸的是,如果我尝试输入其他文本,它将被忽略。似乎该属性Language未在编辑的内容上设置为英语。我试图设置甚至Thread's CurrentCulture并且CurrentUICulture没有结果...
好的,终于我找到了解决该问题的方法。如果您深入研究WPF源,就可以很容易地看出问题:有一个内部类称为TextEditorTyping,该类具有一种称为的方法DoTextInput,该方法负责插入用户输入字符。此方法通过调用设置为插入的范围的培养性质SetSelectedText上TextEditor(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;
}
Run Code Online (Sandbox Code Playgroud)
因此,该方法使用的InputLanguageManager.Current.CurrentInputLanguage是与Windows中当前输入语言相对应的。如果您使用的输入语言不同于英语(这是FrameworkElement.LanguageProperty的默认值),则如果您在RichTextBox中编辑文本,则FlowDocument中插入的元素将以当前输入语言为其Language属性。例如,如果您输入的语言是匈牙利语(hu-hu),则FlowDocument如下所示:
<FlowDocument>
<Paragraph>
<Run xml:lang="hu-hu">asdfasdf</Run>
</Paragraph>
</FlowDocument>
Run Code Online (Sandbox Code Playgroud)
该站点描述了相同的问题。
幸运的是,有一种解决方法。我们已经看过DoTextInput方法的源代码,并且里面有一个using块:
IDisposable disposable = This.Selection.DeclareChangeBlock();
using (disposable)
{
...
// SETTING THE CULTURE ->
This.SetSelectedText(str, InputLanguageManager.Current.CurrentInputLanguage);
...
}
Run Code Online (Sandbox Code Playgroud)
这是一个更改块,位于最后一行-释放后,将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);
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们将已编辑范围的语言重置为适当的值- Document.Language。解决此问题之后,您可以使用WPF拼写检查-例如,法语:
<My:CultureIndependentRichTextBox xml:lang="fr-FR" SpellCheck.IsEnabled="True">
<FlowDocument>
</FlowDocument>
</My:CultureIndependentRichTextBox>
Run Code Online (Sandbox Code Playgroud)
它会神奇地工作。:)