12

On a Computer with culture Setting "de-DE" (or any other than "en-US"), I would like to have a RichTextBox with spell checking enabled, with the checked language set to English ("en-US").

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

This enables the spell check, but checks with "de-DE" culture, rather than "en-US". The same holds when adding xml:lang="en-us".

However,

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

correctly enables spell checking in English, but also changes the Keyboard layout to "en-US".

How can I have the system's keyboard setting (in my case "de-DE"), but the spell checking of the RichTextBox to be English?

(Potentially relevant: I'm using .NET Framework 4.5)

  • I believe (but don't know for sure) that you have to install a language in Windows to enable spell checking. And this is from Windows 8 and onwards. Continuing my speculation, on a German computer when you install the "en-US" language you by default get the "US" keyboard. Setting the input language to "en-US" will switch the keyboard to "US", however, if you remove the "US" keyboard and add the "German" keyboard to the "en-US" language you will keep the "German" keyboard even when spell checking using "en-US". You are able to rotate through languages and keyboards by pressing Windows-Space. – Martin Liversage Dec 30 '15 at 11:52

2 Answers2

4

I have tried to reproduce your problem and for me I could not active spell checker for other language than English, although I have changed Regional Settings and Thread culture before components were initialized:

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

Based on solution provided here, I was able to make it work:

1) Inherit from 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) Use it in your 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">

[edit]

I have also tried to avoid applying the property value for each text change, by defining a timer and spell checking everything from time to time. On my computer, I cannot see the difference when using 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);
    }
}
Community
  • 1
  • 1
Alexei - check Codidact
  • 22,016
  • 16
  • 145
  • 164
  • Thank you, Alexei, this seems to work. However, it makes text input into the RichTextBox visibly slow. Is there a way to not perform the application of language property on each change (i.e. press of a key), but perhaps only after each entered word? – random string Dec 28 '15 at 08:58
  • Can you please specify your content length? I have just added another approach and I am wondering if it is better for your particular case. – Alexei - check Codidact Dec 30 '15 at 11:41
  • Thanks Alexei! We have slow machines ( :-( ), so sometimes it actually is an issue. However, I had some users test the spell-check enabled version and none of them complained about bad performance. So I'll probably just stick with the version without the timer. Thanks again! – random string Dec 30 '15 at 14:50
1

Maybe someone will find this helpful.

I had same problem. I wanted to add spell check in RichTextBox for Serbian Latin and Cyrillic text. To make it work i had to install Windows Language Packs for these two languages. After that this code made it works:

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

For languages like German, French, Italian i think you don't need to install languages packs because they are already installed by default, but for other languages you have to.

Hazaaa
  • 144
  • 2
  • 14