Customize SpellCheck in WPF textbox
While working on a personal project (fleetIt). I worked on Textbox spell check option. I enabled it, it was working fine, until I added a context menu to to the textbox, for custom commands of my application. It was displaying the spelling errors but the suggestions and correction options was not available. Then I tried to customize the context menu such a way that it can display both my custom options as well as the system default spell check options. Here is a simple implementation, which helps to customize the context menu and display the spell check suggestions options.
<Window x:Class="dotnetthoughts.net.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=System"
Title="WPF SpellCheck Demo" Height="350" Width="525" Loaded="Window_Loaded">
<DockPanel>
<TextBox Name="txtEdit" SpellCheck.IsEnabled="True"
AcceptsReturn="True"
ContextMenuOpening="txtEdit_ContextMenuOpening"
VerticalScrollBarVisibility="Visible">
<TextBox.ContextMenu>
<ContextMenu Name="ctxMenu" />
</TextBox.ContextMenu>
</TextBox>
</DockPanel>
</Window>
And here is the code behind
namespace dotnetthoughts.net
{
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void txtEdit_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
int index = 0;
this.txtEdit.ContextMenu.Items.Clear(); //Clearing the existing items
//Getting the spellcheck suggestions.
SpellingError spellingError = this.txtEdit.GetSpellingError(this.txtEdit.CaretIndex);
if (spellingError != null && spellingError.Suggestions.Count() >= 1)
{
//Creating the suggestions menu items.
foreach (string suggestion in spellingError.Suggestions)
{
MenuItem menuItem = new MenuItem();
menuItem.Header = suggestion;
menuItem.FontWeight = FontWeights.Bold;
menuItem.Command = EditingCommands.CorrectSpellingError;
menuItem.CommandParameter = suggestion;
menuItem.CommandTarget = this.txtEdit;
this.txtEdit.ContextMenu.Items.Insert(index, menuItem);
index++;
}
Separator seperator = new Separator();
this.txtEdit.ContextMenu.Items.Insert(index, seperator);
index++;
//Adding the IgnoreAll menu item
MenuItem IgnoreAllMenuItem = new MenuItem();
IgnoreAllMenuItem.Header = "Ignore All";
IgnoreAllMenuItem.Command = EditingCommands.IgnoreSpellingError;
IgnoreAllMenuItem.CommandTarget = this.txtEdit;
this.txtEdit.ContextMenu.Items.Insert(index, IgnoreAllMenuItem);
index++;
}
else
{
//No Suggestions found, add a disabled NoSuggestions menuitem.
MenuItem menuItem = new MenuItem();
menuItem.Header = "No Suggestions";
menuItem.IsEnabled = false;
this.txtEdit.ContextMenu.Items.Insert(index, menuItem);
index++;
}
//.Net 4.0 Supports CustomDictionaries, Option for Adding to dictionary.
int selectionStart = this.txtEdit.GetSpellingErrorStart(this.txtEdit.CaretIndex);
if (selectionStart >= 0)
{
Separator seperator1 = new Separator();
this.txtEdit.ContextMenu.Items.Insert(index, seperator1);
index++;
MenuItem AddToDictionary = new MenuItem();
AddToDictionary.Header = "Add to Dictionary";
//Getting the word to add
this.txtEdit.SelectionStart = selectionStart;
this.txtEdit.SelectionLength = this.txtEdit.GetSpellingErrorLength(this.txtEdit.CaretIndex);
//Ignoring the added word.
AddToDictionary.Command = EditingCommands.IgnoreSpellingError;
AddToDictionary.CommandTarget = this.txtEdit;
AddToDictionary.Click += (object o, RoutedEventArgs rea) =>
{
this.AddToDictionary(this.txtEdit.SelectedText);
};
this.txtEdit.ContextMenu.Items.Insert(index, AddToDictionary);
index++;
}
//Common Edit MenuItems.
Separator seperator2 = new Separator();
this.txtEdit.ContextMenu.Items.Insert(index, seperator2);
index++;
//Cut
MenuItem cutMenuItem = new MenuItem();
cutMenuItem.Command = ApplicationCommands.Cut;
this.txtEdit.ContextMenu.Items.Insert(index, cutMenuItem);
index++;
//Copy
MenuItem copyMenuItem = new MenuItem();
copyMenuItem.Command = ApplicationCommands.Copy;
this.txtEdit.ContextMenu.Items.Insert(index, copyMenuItem);
index++;
//Paste
MenuItem pasteMenuItem = new MenuItem();
pasteMenuItem.Command = ApplicationCommands.Paste;
this.txtEdit.ContextMenu.Items.Insert(index, pasteMenuItem);
index++;
Separator seperator3 = new Separator();
this.txtEdit.ContextMenu.Items.Insert(index, seperator3);
index++;
//Delete
MenuItem deleteMenuItem = new MenuItem();
deleteMenuItem.Command = ApplicationCommands.Delete;
this.txtEdit.ContextMenu.Items.Insert(index, deleteMenuItem);
index++;
Separator seperator4 = new Separator();
this.txtEdit.ContextMenu.Items.Insert(index, seperator4);
index++;
//Select All
MenuItem selectAllMenuItem = new MenuItem();
selectAllMenuItem.Command = ApplicationCommands.SelectAll;
this.txtEdit.ContextMenu.Items.Insert(index, selectAllMenuItem);
index++;
}
//Method to Add text to Dictionary
private void AddToDictionary(string entry)
{
using (StreamWriter streamWriter = new StreamWriter(@"D:\WPF\MyCustomDictionary.lex", true))
{
streamWriter.WriteLine(entry);
}
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Assigning custom Dictionary to TextBox
this.txtEdit.SpellCheck.CustomDictionaries.Add(new Uri(@"D:\WPF\MyCustomDictionary.lex"));
}
}
}
The .Net Framework 4.0 supports CustomDictionaries, which helps to create your own Dictionary.
//.Net 4.0 Supports CustomDictionaries, Option for Adding to dictionary.
int selectionStart = this.txtEdit.GetSpellingErrorStart(this.txtEdit.CaretIndex);
if (selectionStart >= 0)
{
Separator seperator1 = new Separator();
this.txtEdit.ContextMenu.Items.Insert(index, seperator1);
index++;
MenuItem AddToDictionary = new MenuItem();
AddToDictionary.Header = "Add to Dictionary";
//Getting the word to add
this.txtEdit.SelectionStart = selectionStart;
this.txtEdit.SelectionLength = this.txtEdit.GetSpellingErrorLength(this.txtEdit.CaretIndex);
//Ignoring the added word.
AddToDictionary.Command = EditingCommands.IgnoreSpellingError;
AddToDictionary.CommandTarget = this.txtEdit;
AddToDictionary.Click += (object o, RoutedEventArgs rea) =>
{
this.AddToDictionary(this.txtEdit.SelectedText);
};
this.txtEdit.ContextMenu.Items.Insert(index, AddToDictionary);
index++;
}
Here is the screenshot of Demo Application.




