WPF has an inbuilt feature of Spellchecking. In this article I have explored the SpellCheck functionality of WPF TextBoxBase object.
CustomDictionaries introduced with WPF 4.0 is also discussed with this article
Introduction
WPF comes with an inbuilt feature of
SpellCheck.
SpellCheck is added to
TextBoxBase object, which inherits all the textual input controls automatically. Thus any input control will automatically derive the Spell Checking functionality.
In this article I would like to introduce how you can explore this feature to your own application.
Basic Usage
WPF provides a new object called
SpellCheck. This object can be applied to any
TextBoxBase object and thereby the object will behave automatically with the
spellcheck functionality. To do this, lets look at the example :
<StackPanel Height="150" Margin="50">
<TextBlock Text="Enter Content" ></TextBlock>
<TextBox x:Name="txtBox" SpellCheck.IsEnabled="True" AcceptsReturn="True" />
</StackPanel>
In the above example, you can see the
TextBox txtBox, have
SpellChecker enabled. This ensures the textbox automatically detect misspelled words and will put an underline on the word. When you run the application, you will see the textbox to appear like this :

You can see all the misspelled word is shown with red underline. These words can easily be corrected by using the
TextBox default
ContextMenu. Right clicking on the word will give you a list of suggestions for the current word which you might choose to change the word in the paragraph.
SpellCheck.IsEnabled is actually a
Dependency property. So you can easily use it to set in
Style setters. You can also use global setter to apply SpellChecking to every control you put in the window very easily.
<Style TargetType="{x:Type TextBoxBase}" x:Key="txtBasic" >
<Setter Property="SpellCheck.IsEnabled" Value="true" />
<Setter Property="SpellCheck.SpellingReform" Value="PreAndPostreform" />
</Style>
Now you can easily define any TextBox or RichTextBox or any control that derives TextboxBase and use the Style to apply SpellChecker. You can also use
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource txtBasic}" />
<Style TargetType="{x:Type RichTextBox}" BasedOn="{StaticResource txtBasic}" />
By doing this, any TextBox or RichTextBox which you place in your Window will automatically have spellChecking enabled.
You can also enable/disable the SpellCheck from codebehind.
SpellCheck.SetIsEnabled(txtBox, true);
SpellCheck.SetSpellingReform(txtBox, SpellingReform.PreAndPostreform);
Spelling error can be detected based on the carat location. TextBoxBase contains a few methods that you can invoke to get Spelling errors. SpellingError is a class which provides the current Spelling error word with an enumerable of Suggessions.
Lets say you want to display the suggessions into your own Listbox.
<TextBlock Text="Enter Content" ></TextBlock>
<TextBox x:Name="txtBox" AcceptsReturn="True" Keyboard.KeyUp="txtBox_KeyUp"/>
<TextBlock Text="Suggessions" ></TextBlock>
<ListBox x:Name="lstSuggessions" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Thus you can see, I have declared a ListBox which will show you the Suggessions that are populated in the contextmenu. To do this you can write like this :
private void txtBox_KeyUp(object sender, KeyEventArgs e)
{
int catatPos = txtBox.CaretIndex;
lstSuggessions.Items.Clear();
SpellingError error = txtBox.GetSpellingError(catatPos);
if (error != null)
{
foreach (string suggession in error.Suggestions)
lstSuggessions.Items.Add(suggession);
}
}
Here we are using SpellingError class to get the Suggessions. CaretIndex returns the index where the carat is in the textbox. GetSpellingError can return SpellingError object only when the current Carat location has a word with errors and also SpellCheck is enabled for the TextBox.

You can use EditingCommands.CorrectSpellingError to correct the spelling.
Building ContextMenu
It is true that the default contextmenu cannot be styled. You need to redefine the contextMenu again to have it styled. Let us look how you can redefine the
ContextMenu yourself.
private void txtBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
ContextMenu menu = this.Resources["ctxMenu"] as ContextMenu;
this.ClearSpellCheckMenuItems(menu);
int catatPos = txtBox.CaretIndex;
SpellingError error = txtBox.GetSpellingError(catatPos);
if (error != null)
{
this.txtBox.ContextMenu.Items.Insert(0, new Separator());
MenuItem item = this.GetMenu("Ignore All", EditingCommands.IgnoreSpellingError, this.txtBox);
item.Tag = "S";
this.txtBox.ContextMenu.Items.Insert(0, item);
foreach (string suggession in error.Suggestions)
{
item = this.GetMenu(suggession, EditingCommands.CorrectSpellingError, this.txtBox);
item.Tag = "S";
this.txtBox.ContextMenu.Items.Insert(0, item);
}
}
}
private MenuItem GetMenu(string header, ICommand command, TextBoxBase target)
{
MenuItem item = new MenuItem();
item.Header = header;
item.Command = command;
item.CommandParameter = header;
item.CommandTarget = target;
return item;
}
private void ClearSpellCheckMenuItems(ContextMenu menu)
{
for (int i = 0; i < menu.Items.Count; i++)
{
MenuItem item = menu.Items[i] as MenuItem;
if (item != null && item.Tag != null)
menu.Items.RemoveAt(i);
}
}
Here I have built the contextmenu dynamically. The
EditingCommand.CorrectSpellingError will take a string parameter which I have passed from Suggession and the target as the control. The GetMenu will build every menuItem.
IgnoreAll can also be created using
EditingCommand.IgnoreSpellingError.
It is to be noted that I have added each menuitem from the beginning. It is because each item is added at 0th index so that each new item will come above the other. It is preferable to use the reverse always.
Limitation of SpellCheck
SpellCheck of WPF has few basic Limitations.
- SpellChecking functionality is restricted to English, Spanish, French and German.
- You cannot create CustomDictionaries for Textboxes. So if you want to ignore a specific word, it will be ignored once only for the current application run. If you rerun the application, you need to ignore the same word again.
CustomDictionaries with WPF 4.0
With the introduction of WPF 4.0,
SpellCheck object is somehow modified to support
CustomDictionaries. This is really a good addition to WPF Spell Checker. Let us look how you can use it:
<TextBox x:Name="txtCustom" SpellCheck.IsEnabled="True">
<SpellCheck.CustomDictionaries>
<sys:Uri>location\dictionary.lex</sys:Uri>
</SpellCheck.CustomDictionaries>
</TextBox>
In the above Code you can see I have added custom dictionaries to the
TextBox. sys points to System in System.dll(
xmlns:sys="clr-namespace:System;assembly=System"). CustomDictionaries is a collection of all dictionaries which you can add to your textbox control so that when text is entered into the textbox it will ignore if misspelled but exists in the
CustomDictionary file.
CustomDictionary file is actually a Text file which have every words placed in new lines. While loading the textbox, WPF reads the entire file into context and recreates its dictionary dynamically.
You can also create a custom
"Add to Dictionary" to add the current item into dictionary. To do this,
MenuItem item = new MenuItem();
item.Header = "Add to Dictionary";
item.Click += new RoutedEventHandler(AddDict_Click);
item.Command = EditingCommands.IgnoreSpellingError;
item.CommandParameter = currentText;
item.CommandTarget = txtBox;
So now the
AddDict_Click will be called automatically when we select the Add To Dictionary object. You can see I have also used item.Command as
EditingCommands.IgnoreSpellingError, which will ignore the word to current textbox. Thus you only need to write the logic to open the Dictionary file and write the element in
CommandParameter to the file.
Conclusion
SpellCheck is a great option to WPF. You can easily use it to build a better solution for your client. I hope this article will help you to a great extent. Please feel free to write your feedback.