Check Spelling as You Type
TX Spell .NET doesn't need TX Text Control. Its spell checker checks any text you pass to it, so the standard RichTextBox of WPF can mark misspelled words while the user types. You build a small application that does this: a new project with the TX Spell .NET package, a spell checker declared in XAML, a RichTextBox, and an event handler that colors every misspelled word red.
Prerequisites
- Visual Studio on Windows with .NET 8 or higher.
- The setup of TX Spell .NET for WPF 11.0, the full or the trial version, installed on your machine. It provides the package source Text Control Offline Packages. See Installing the Product.
Create the Project
- Open Visual Studio and create a new project.
- Select C# from the Languages list, Windows from the Platform list and Desktop as the Project Type.
- Select the project template WPF Application and click Next.
- Enter a project name, RtbSample in this tutorial, and click Next.
- Select .NET 8 or higher as the Framework and click Create.
Install the NuGet Package
- Select the project in Solution Explorer and choose Project > Manage NuGet Packages....
- Select Text Control Offline Packages in the Package source list and click Browse.
- Select
TXTextControl.TXSpell.WPF.SDKand click Install.
This one package is all you need: it contains the spell checker with its dialogs and menus, and your license. The package of TX Text Control is not required. Package Overview lists what the packages contain.
Declare the Spell Checker and the RichTextBox
Replace the contents of MainWindow.xaml with this markup. If your project has another name, change RtbSample in x:Class to it:
<Window x:Class="RtbSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:spell="clr-namespace:TXTextControl.WPF.Proofing;assembly=TXSpell.WPF"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<spell:TXSpellChecker x:Key="txSpellChecker1" />
</Window.Resources>
<DockPanel>
<RichTextBox x:Name="richTextBox1" TextChanged="richTextBox1_TextChanged" />
</DockPanel>
</Window>
The markup works as follows:
- The
spellprefix maps theTXTextControl.WPF.Proofingnamespace of the TXSpell.WPF assembly. <spell:TXSpellChecker x:Key="txSpellChecker1" />creates the TXSpellChecker as a resource of the window. It has no user interface of its own.TextChangednames the handler that checks the text on every change.
Write the Code
Replace the class in MainWindow.xaml.cs with the following code, inside the namespace of the project:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using TXTextControl.Proofing;
using TXTextControl.WPF.Proofing;
public partial class MainWindow : Window
{
private readonly TXSpellChecker txSpellChecker1;
// Set while the handler colors words, which changes the RichTextBox itself
private bool isColoring;
public MainWindow()
{
InitializeComponent();
// The spell checker declared in Window.Resources
txSpellChecker1 = (TXSpellChecker)FindResource("txSpellChecker1");
// Without a connected TextControl, initialize the spell checker yourself
txSpellChecker1.Create();
}
private void richTextBox1_TextChanged(object sender, TextChangedEventArgs e)
{
if (isColoring) return;
isColoring = true;
FlowDocument document = richTextBox1.Document;
TextRange all = new TextRange(document.ContentStart, document.ContentEnd);
// Start with all text black, so that corrected words lose their color
all.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black);
// Check the whole text and color each incorrect word red
txSpellChecker1.Check(all.Text);
foreach (IncorrectWord incorrectWord in txSpellChecker1.IncorrectWords)
{
GetRange(document, incorrectWord).ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);
}
isColoring = false;
}
// The part of the document that holds an incorrect word found in its text
private static TextRange GetRange(FlowDocument document, IncorrectWord incorrectWord)
{
return new TextRange(
GetTextPointerAtOffset(document, incorrectWord.Start),
GetTextPointerAtOffset(document, incorrectWord.Start + incorrectWord.Length));
}
// Finds the position of a character index of the document's text, as TextRange.Text returns it
private static TextPointer GetTextPointerAtOffset(FlowDocument document, int offset)
{
TextPointer pointer = document.ContentStart;
while (pointer != null)
{
TextPointerContext context = pointer.GetPointerContext(LogicalDirection.Forward);
if (context == TextPointerContext.Text)
{
int length = pointer.GetTextRunLength(LogicalDirection.Forward);
if (offset <= length) return pointer.GetPositionAtOffset(offset);
offset -= length;
}
else if ((context == TextPointerContext.ElementEnd && pointer.Parent is Paragraph) ||
(context == TextPointerContext.ElementStart && pointer.GetAdjacentElement(LogicalDirection.Forward) is LineBreak))
{
// The text has a line break at the end of a paragraph and at a LineBreak
if (offset < Environment.NewLine.Length) return pointer;
offset -= Environment.NewLine.Length;
}
pointer = pointer.GetNextContextPosition(LogicalDirection.Forward);
}
return document.ContentEnd;
}
}
What the Code Does
FindResourcereturns the spell checker that XAML created. A resource creates no field in the code-behind, so the constructor stores it in one.- Create initializes the spell checker. A
TextControldoes this when you connect it; with any other control, call it once before the first check. - Check checks the text of the document, which a
TextRangefrom its start to its end returns. IncorrectWords then holds the incorrect words. - Each IncorrectWord has a Start, a character index of that text counting from 0, and a Length. A WPF document is not a string, so
GetTextPointerAtOffsetwalks through it and counts characters to find the matching position. Paragraph ends and line breaks count as a line break in the text, asTextRange.Textwrites them. ApplyPropertyValuecolors a range. Because coloring changes the document, theisColoringflag keeps the handler from starting again while it runs.
Run the Application
Press F5 and type a sentence with a spelling mistake, such as Wrong wordd. The misspelled word turns red; correct it, and it turns black again. A sample of the setup checks the text the same way, with several RichTextBox controls that share one spell checker, and colors the misspelled word at the caret:

The handler checks the whole text on every change. A word is therefore red while it is still incomplete, and the check takes longer as the text grows. TX Text Control, which underlines words once they are complete, does this for you; see Create Your First WPF Application. For a TextBox, a validation rule is often enough, as As-You-Type Checking shows.
Next Steps
- Open the Spell Check Dialog: let the user correct the words of the
RichTextBoxin a dialog. - Incorrect Words and Suggestions: create suggestions for the words
Checkfound. - Checking Multiple Controls: share one spell checker between several controls.