拼写检查不适用于 WPF RichTextBox [英] Spell checking doesn't work with WPF RichTextBox

查看:104
本文介绍了拼写检查不适用于 WPF RichTextBox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to enable spell checking in a WPF RichTextBox. MSDN writes that System.Windows.Controls.SpellCheck can be used to enable spell checking for TextBox and RichTextBox controls.

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

Unfortunately, the following code doesn't work for me:

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

这很奇怪,因为如果我使用纯文本框,它工作得很好(如果我拼错了一些东西,我可以看到红线).

Which is strange, because if I use a plain TextBox, it works perfectly fine (I can see the red lines if I miss-spell something).

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

Unfortunately, every answer I've found on SO so far mention only to set SpellCheck.IsEnabled to True and set the Language property to one of the supported languages, but I have no idea why does this method not work on my computer in case of built-in RichTextBoxes?

更新:

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

If I write that, the text in the run will be underlined:

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

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

But unfortunately, if I try to enter some other text, it will be ignored. It looks like that the property Language is not setted to english on the edited content. I've tried to set even the Thread's CurrentCulture and CurrentUICulture with no result...

推荐答案

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

Okay, finally I have figured out the solution for the issue. The problem can be easily seen if you dig into the WPF source: there is an internal class called TextEditorTyping which has a method called DoTextInput which takes care of inserting user input characters. This method sets the culture property for the inserted range through calling SetSelectedText on TextEditor (TextEditor is another internal class providing text editing services for various controls, such as RichTextBox). Here is that part of the DoTextInput method:

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 将如下所示:

So the method is using the InputLanguageManager.Current.CurrentInputLanguage which corresponds to the current input language in Windows. If you use an input language which is different than English (which is the default value for FrameworkElement.LanguageProperty) then if you edit the text in your RichTextBox, the inserted element in the FlowDocument would have the current input language as its Language property. For example, if your input language is Hungarian (hu-hu), your FlowDocument would look like this:

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

本网站描述了同样的问题.

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

Fortunately, there is a workaround for that. We have already seen the source of the DoTextInput method, and there is a using block inside that:

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

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

This is a change block which gets disposed at the last line - after it gets disposed, the TextContainerChanged event is fired which we can handle by overriding the OnTextChanged method of 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);
}

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

Here we are resetting the Language of the edited range to the proper value - to Document.Language. After this workaround, you can use WPF spellchecking - for example, in French:

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

它会神奇地起作用.:)

And it will magically work. :)

这篇关于拼写检查不适用于 WPF RichTextBox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆