SpellCheck As You Type with RadRichTextBox
| Date Posted | Product | Author |
|---|---|---|
| April 25, 2014 | RadRichTextBox | Georgi Georgiev |
How To
This article will demonstrate how to implement spellcheck as you type functionality in RadRichTextBox. Here is how our spell chcked RadRichTextBox will look like at the end:

Solution
First of all, we will need a derived class from RadRichTextBox:
public class SpellCheckRichTextBox : RadRichTextBox
{ }
Then we will need an instance of RadSpellChecker which will be used to check the words:
protected override void CreateChildItems(Telerik.WinControls.RadElement parent)
{
base.CreateChildItems(parent);
this.spellChecker = new RadSpellChecker();
this.controlSpellChecker = this.spellChecker.GetControlSpellChecker(typeof(RadRichTextBox));
this.controlSpellChecker.CurrentControl = this;
}
Spell-checking will be performed when the Spacekey is pressed. We can override the OnKeyDown event and execute any spellchecking logic from there:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Space)
{
this.SpellCheckCore(this.GetCurrentWord());
}
base.OnKeyDown(e);
}
At this point, you are probably wondering what the SpellCheckCore and GetCurrentWord methods do. The GetCurrentWord method will get the word where the cursor is as a string by using the RadRichTextBox API:
private string GetCurrentWord()
{
DocumentPosition endPosition = new DocumentPosition(this.Document.CaretPosition);
DocumentPosition startPosition = new DocumentPosition(endPosition);
this.SelectCurrentWord(startPosition);
string lastWord = this.Document.Selection.GetSelectedText();
this.Document.Selection.Clear();
return lastWord;
}
On the other hand, the SpellCheckCore method will check whether a word is correct, and if it is not, it will be underlined. Also, if the word is a part of the IgnoredWords in the SpellChecker, it will be skipped:
protected virtual void SpellCheckCore(string word)
{
if (string.IsNullOrEmpty(word) || this.controlSpellChecker.IgnoredWords.ContainsWord(word))
{
return;
}
this.SelectCurrentWord(this.Document.CaretPosition);
if (this.AutoReplaceOnSpellCheck)
{
string[] suggestions = (string[])this.ControlSpellChecker.SpellChecker.GetSuggestions(this.Document.Selection.GetSelectedText());
if (suggestions.Length > 0)
{
this.Insert(suggestions[0]);
}
}
else
{
if (!controlSpellChecker.SpellChecker.CheckWordIsCorrect(word))
{
this.ChangeUnderlineDecoration(Telerik.WinControls.RichTextBox.UI.UnderlineType.Wave);
this.Document.Selection.Clear();
this.ChangeUnderlineDecoration(Telerik.WinControls.RichTextBox.UI.UnderlineType.None);
}
else
{
this.ChangeUnderlineDecoration(Telerik.WinControls.RichTextBox.UI.UnderlineType.None);
this.Document.Selection.Clear();
}
}
}
The If statement, which checks the AutoReplaceOnSpellCheck property, is used to replace the current word, if it is incorrect with the first suggestion in the dictionary. After our Control is capable of spellchecking while we are typing, we can implement a context menu to see a list of suggestions and use the Copy/Paste/Undo/Delete/SelectAll actions. Here is how the context menu can be built in a single method:
private RadDropDownMenu BuildContextMenu(SpanLayoutBox spanBox)
{
RadDropDownMenu menu = new RadDropDownMenu();
RadMenuItem menuItem;
if (this.Document.Selection.IsEmpty && this.IsSpellCheckingEnabled && spanBox != null)
{
this.Document.CaretPosition.MoveToInline(spanBox, 0);
string spanBoxTextAlphaNumericOnly = String.Concat(spanBox.Text.TakeWhile(c => char.IsLetterOrDigit(c)));
if (spanBoxTextAlphaNumericOnly.Length > 0 && !this.ControlSpellChecker.SpellChecker.CheckWordIsCorrect(spanBoxTextAlphaNumericOnly))
{
string[] suggestions = (string[])this.ControlSpellChecker.SpellChecker.GetSuggestions(spanBox.Text);
if (suggestions.Length <= 0)
{
menuItem = new RadMenuItem("(No Spelling Suggestions)");
menuItem.Enabled = false;
menu.Items.Add(menuItem);
}
foreach (string suggestion in suggestions)
{
menuItem = new RadMenuItem(suggestion);
menuItem.Click += (object sender, EventArgs e) => { this.ReplaceCurrentWord(spanBox, (sender as RadMenuItem).Text); };
menu.Items.Add(menuItem);
}
menu.Items.Add(new SeparatorElement());
menuItem = new RadMenuItem("Add to Dictionary");
menuItem.Click += (object sender, EventArgs e) => { this.ControlSpellChecker.SpellChecker.AddWord(spanBoxTextAlphaNumericOnly); };
menu.Items.Add(menuItem);
menu.Items.Add(new SeparatorElement());
}
}
menuItem = new RadMenuItem("Undo");
menuItem.Click += (object sender, EventArgs e) => { this.Undo(); };
menu.Items.Add(menuItem);
menu.Items.Add(new SeparatorElement());
menuItem = new RadMenuItem("Cut");
menuItem.Click += (object sender, EventArgs e) => { this.Cut(); };
menu.Items.Add(menuItem);
menuItem = new RadMenuItem("Copy");
menuItem.Click += (object sender, EventArgs e) => { this.Copy(); };
menu.Items.Add(menuItem);
menuItem = new RadMenuItem("Paste");
menuItem.Click += (object sender, EventArgs e) => { this.Paste(); };
menu.Items.Add(menuItem);
menuItem = new RadMenuItem("Delete");
menuItem.Click += (object sender, EventArgs e) => { this.Delete(false); };
menu.Items.Add(menuItem);
menu.Items.Add(new SeparatorElement());
menuItem = new RadMenuItem("Select All");
menuItem.Click += (object sender, EventArgs e) => { this.Document.Selection.SelectAll(); };
menu.Items.Add(menuItem);
return menu;
}
We can easily show it on Right Mouse Click:
protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
SpanLayoutBox spanBox = this.Document.GetLayoutBoxByPosition(e.Location) as SpanLayoutBox;
this.BuildContextMenu(spanBox).Show(this, e.Location);
}
base.OnMouseDown(e);
}
A complete solution in C# and VB.NET can be found here.