【问题标题】:conflicting language settings of WPF richtextboxWPF富文本框的语言设置冲突
【发布时间】:2016-03-29 20:17:58
【问题描述】:

在具有文化设置“de-DE”(或“en-US”以外的任何其他)的计算机上,我想要一个启用拼写检查的 RichTextBox,检查的语言设置为英语(“en-US” ")。

<RichTextBox SpellCheck.IsEnabled="True" Language="en-US"/>

这会启用拼写检查,但会检查“de-DE”文化,而不是“en-US”。添加xml:lang="en-us"时也是如此。

然而,

<RichTextBox SpellCheck.IsEnabled="True" InputLanguageManager.InputLanguage="en-US"/>

正确启用英语拼写检查,但也将键盘布局更改为“en-US”。

我怎样才能有系统的键盘设置(在我的情况下是“de-DE”),但 RichTextBox 的拼写检查是英文的?

(可能相关:我使用的是 .NET Framework 4.5)

【问题讨论】:

  • 我相信(但不确定)您必须在 Windows 中安装一种语言才能启用拼写检查。这是从 Windows 8 及更高版本开始的。继续我的猜测,在德国计算机上,当您安装“en-US”语言时,默认情况下会获得“US”键盘。将输入语言设置为“en-US”会将键盘切换为“US”,但是,如果您删除“US”键盘并将“German”键盘添加到“en-US”语言,您将保留“German” " 键盘,即使在使用“en-US”进行拼写检查时也是如此。您可以通过按 Windows-Space 来切换语言和键盘。

标签: c# .net wpf windows richtextbox


【解决方案1】:

我已尝试重现您的问题,但对我来说,我无法为除英语之外的其他语言启用拼写检查器,尽管我在组件初始化之前更改了区域设置和线程文化:

    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("de-DE");
    Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("de-DE");

根据here 提供的解决方案,我能够使其工作:

1) 从 RichTextBox 继承:

class RichTextBoxEx : 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);
    }
}

2) 在您的 xaml 中使用它

<local:RichTextBoxEx x:Name="richTextBox" HorizontalAlignment="Left" Height="100" Margin="33,100,0,0" VerticalAlignment="Top" Width="474" 
             xml:lang="de-DE" SpellCheck.IsEnabled="True">

[编辑]

我还尝试通过定义计时器和不时检查所有内容来避免对每个文本更改应用属性值。在我的电脑上,使用the longest Wikipedia article content时看不到区别:

class RichTextBoxEx : RichTextBox
{
    DispatcherTimer timer;
    bool textChanged = false;

    public RichTextBoxEx()
    {
        if (DesignerProperties.GetIsInDesignMode(this))
            return;

        timer = new DispatcherTimer();
        timer.Interval = new TimeSpan(0, 0, 1);
        timer.Tick += timer_Tick;
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        try
        {
            var range = new TextRange(Document.ContentStart, Document.ContentEnd);
            range.ApplyPropertyValue(FrameworkElement.LanguageProperty, Document.Language);
        }
        finally
        {
            textChanged = false;
        }
    }

    protected override void OnTextChanged(TextChangedEventArgs e)
    {
        // TODO: remove if timer version works correctly
        //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);
        //        }
        //    }
        //}

        textChanged = true;
        base.OnTextChanged(e);
    }
}

【讨论】:

  • 谢谢你,Alexei,这似乎有效。但是,它会使文本输入到 RichTextBox 中明显变慢。有没有办法在每次更改时不应用语言属性(即按下一个键),但可能只在每个输入的单词之后应用?
  • 您能指定您的内容长度吗?我刚刚添加了另一种方法,我想知道它是否更适合您的特定情况。
  • 谢谢阿列克谢!我们的机器很慢( :-( ),所以有时它实际上是一个问题。但是,我让一些用户测试了启用拼写检查的版本,但没有人抱怨性能不佳。所以我可能会坚持使用该版本没有计时器。再次感谢!
【解决方案2】:

也许有人会觉得这很有帮助。

我有同样的问题。我想在 RichTextBox 中为塞尔维亚拉丁文和西里尔文添加拼写检查。为了使它工作,我必须为这两种语言安装 Windows 语言包。 之后这段代码使它工作:

Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("sr-Cyrl"); // Change language name to what you need
richTextBox1.Language = XmlLanguage.GetLanguage(Thread.CurrentThread.CurrentCulture.Name);

对于德语、法语、意大利语等语言,我认为您不需要安装语言包,因为它们已经默认安装,但对于其他语言,您必须安装。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多