Thursday, August 5, 2010

Spell Check for WPF Text entry

WPF provides support of spell checking for the text entered by user. This spell check feature is independent of any software already installed (like Microsoft office). If we enter any misspelled word then it is underlined grasping immediate user attention by providing the visual cue. Enabling this feature would result in the behavior as below if any word is misspelled:



Enabling Spell Check:
Spell check can be enabled by setting IsEnabled property of SpellCheck object in TextBox to true.
<TextBox Height="138" Name="textBox1" Width="451" SpellCheck.IsEnabled="True" />

Spell check can also be enabled / disabled through code. Just set the IsEnabled property of the SpellCheck in TextBoxBase to True for enabling spell checking and false otherwise.

Spelling and Language reforms:
This refers to French and German language reforms. If we set this property for any other language, its value has no effect. The value is set based on enum. The possible values are:

- PreAndPostreform: Default value for French language. Uses the combination of spelling as before and after the reforms in spellings.

- Prereform: Only uses the spellings before the reform.

- Postreform: Default value for German language. It only uses the spelling after the reform in the language.

Specifying language for spell check:
We might specify the language for spell checking by setting the Language attribute of the FrameworkElement. The spell checking for different cultures are different even if the language is same, e.g. U.S English spellings can be specified as en-US and the British spelling might be set as en-GB.

Let's develop a window with two text boxes. Both text boxes check spelling for the text entered. One text box is specified with U.S. English as language and the other is specified as British English.

<Window x:Class="WPFSpellCheck.WindowSpellCheck"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowSpellCheck" Height="367" Width="631">
<Grid Height="330">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="330*" />
<ColumnDefinition Width="68*" />
<ColumnDefinition Width="211*" />
</Grid.ColumnDefinitions>
<Label Height="26" HorizontalAlignment="Left" Margin="12,4,0,0" Name="label1"
VerticalAlignment="Top" Width="151">British English Spell Check</Label>
<TextBox Margin="14,26,12,0" Name="textBox1" SpellCheck.IsEnabled="True" Language="en-GB" Grid.ColumnSpan="3" Height="135" VerticalAlignment="Top" />
<Label HorizontalAlignment="Left" Margin="13,163,0,141" Name="label2" Width="136">U.S. English Spell Check</Label>
<TextBox Margin="14,0,12,12" Name="textBox2" Height="133" VerticalAlignment="Bottom"
SpellCheck.IsEnabled="True" Language="en-US" Grid.ColumnSpan="3" />
</Grid>
</Window>

When we run this the following Window appears. There are various words which are spelled differently in british and american english e.g. colour (UK) and color (US). So as soon as we type color in first text box, it is highlighted as misspelled. You can see the otherwise effect in the second text box.


You might need to install language pack for the intended language based on your operating system. They are required for WinXP. The language packs for .net framework 3.5 sp1 can be downloaded from here:

http://www.microsoft.com/downloads/details.aspx?FamilyID=8489ed13-b831-4855-96f7-dd35e4c02a20&displaylang=en

The installation experience of the language pack is in the same language. So if you are installing Arabic language pack then the installer's instructions are also in Arabic and there seems to be no option to change the language. This might be some issues for developers who are developing applications for languages they don't understand. Let's download the Spanish Language pack and use it from the link above.

<Window x:Class="WPFSpellCheck.WindowSpellCheck"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowSpellCheck" Height="367" Width="631">
<Grid Height="330">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="330*" />
<ColumnDefinition Width="68*" />
<ColumnDefinition Width="211*" />
</Grid.ColumnDefinitions>
<Label Height="26" HorizontalAlignment="Left" Margin="12,4,0,0" Name="label1"
VerticalAlignment="Top" Width="151">U.S. English Spell Check</Label>
<TextBox Margin="14,26,12,0" Name="textBox1" SpellCheck.IsEnabled="True" Language="en-US" Grid.ColumnSpan="3" Height="135" VerticalAlignment="Top" />
<Label HorizontalAlignment="Left" Margin="13,163,0,141" Name="label2" Width="136">Spanish Spell Check</Label>
<TextBox Margin="14,0,12,12" Name="textBox2" Height="133" VerticalAlignment="Bottom"
SpellCheck.IsEnabled="True" Language="es-ES" Grid.ColumnSpan="3" />
</Grid>
</Window>

So we have created two text boxes, the first is expecting the text entry in U.S english and the other is expecting text entry in Espanol (Spanish). When you run the application, it appears as follows:



Note:
If you are using Language pack for supporting a particular language then you must not forget to provide support of installation of the language pack during installation of your software.

Custom Dictionaries:
.Net 4.0 added support of adding custom dictionary to augment the spell check feature of WPF. All you have to define is a lexicon file (*.lex). The list of words in the lexicon file would be considered as legitimate and wouldn't be marked as error providing error visual cues.
<TextBox x:Name="textBox1" SpellCheck.IsEnabled="True">
<SpellCheck.CustomDictionaries>
<sys:Uri>dictionaries\dictionary.lex</sys:Uri>
</SpellCheck.CustomDictionaries>
</TextBox>

Here dictionary.lex is a lexicon file. By default the list of words in the lexicon file would not be marked as spelling error irrespective of the Language. However, you can set so that the lexicon file is applied for a specific locale. This is specified by setting locale ID (#LID) followed by the language specific number in the beginning of lexicon file.

#LID 4106 (Spanish - Guatemala)
#LID 1031 (German - Germany)
#LID 1036 (French - France)
#LID 1033 (English - United States)
#LID 2057 (English - United Kingdom)
#LID 1056 (Urdu) (Not supported by WPF Spell Check yet)

The reference chart of locale - ids is available here:

http://msdn.microsoft.com/en-us/goglobal/bb964664.aspx

There is no settings for providing Add to Dictionary to the user. But this feature might be provided by adding a MenuItem to the context menu of the text box. When the user selects this option, you might add the word to the same lexicon file being used. You might get the error at the current caret location in the text box as follows:
SpellingError error = this.textBox1.GetSpellingError(this.textBox1.CaretIndex - 1);

SpellingError not only gives you the error at the specified index. It also provides the list of suggestions (correct word). You can correct the word using Correct() method of SpellingError object (error in above code). As in the code below, we are correcting the error with the first suggestion available:
error.Correct(error.Suggestions.First());

Limitations:
WPF spell checker (even in .net 4.0) is only limited to four languages. These languages include English, Spanish, French and German. This means that even if you install the language pack for the language (e.g. Arabic), it just wouldn't work.

No comments: