SpellingCorrectionUIProvider: Creating a Spelling Correction User Interface

To provide a fully customized or integrated user interface, it is often required to build new dialogs and forms. With TX Spell's SpellingCorrectionUIProvider class, it is very simple to use data binding to achieve that goal without having to deal with events. Data binding in .NET serves the purpose to provide a simple and reliable way to interact with and display data and different states.

The following three articles give an insight into building custom spelling correction forms and dialogs by using the SpellingCorrectionUIProvider class which is provided by the TXSpellChecker.SpellingCorrectionUIProvider property.

The corresponding sample projects are contained in the following directories

  • %USERPROFILE%\My Documents\TX Spell 7.0.NET for WPF\Samples\WPF\CSharp\TextControl\SpellingCorrectionUIProvider
  • %USERPROFILE%\My Documents\TX Spell 7.0.NET for WPF\Samples\WPF\VB.NET\TextControl\SpellingCorrectionUIProvider

The sample project SpellingCorrectionUIProvider Simple shows how to set the suggestions in the System.Windows.Controls.ListBox automatically and the IsEnabled state for each System.Windows.Controls.Button without using additional code. Furthermore, it explains how to connect a TextControl to the SpellingCorrectionUIProvider and handle its misspelled words by using the change, delete and ignore methods.

The source code is contained in the following directories:

  • %USERPROFILE%\My Documents\TX Spell 7.0.NET for WPF\Samples\WPF\CSharp\TextControl\SpellingCorrectionUIProvider\SpellingCorrectionUIProvider Simple
  • %USERPROFILE%\My Documents\TX Spell 7.0.NET for WPF\Samples\WPF\VB.NET\TextControl\SpellingCorrectionUIProvider\SpellingCorrectionUIProvider Simple

Relevant API Links

There are 2 different places in the project that need to be handled:

1. The XAML code, where the IsEnabled bindings are set for Buttons and the suggestion ListBox. Additionally, the ListBox's content is updated by an ItemsSource binding with the SuggestionsHandler.Suggestions property and each Button gets a Click event to force the corresponding method.

<ListBox Name="listBoxSuggestions" Grid.Column="1" Margin="7"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1},Path=SpellingCorrectionUIProvider.SuggestionsHandling.IsSuggestionListEnabled}"
    ItemsSource ="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.SuggestionsHandling.Suggestions}">
</ListBox>

<Button Name="buttonChange" VerticalAlignment="Top" Margin="7" Content="Change"
    Click="buttonChange_Click"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsChangeEnabled}">
</Button>

<Button Name="buttonIgnore" VerticalAlignment="Top" Grid.Column="1" Margin="7" Content="Ignore"
    Click="buttonIgnore_Click"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsIgnoreEnabled}">
</Button>

<Button Name="buttonDelete" VerticalAlignment="Top" Grid.Column="2" Margin="7" Content="Delete"
    Click="buttonDelete_Click"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsDeleteEnabled}">
</Button>
private void buttonChange_Click(object sender, RoutedEventArgs e)
{
    // change the current misspelled word with the suggestion selected in the ListBox
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Change(listBoxSuggestions.SelectedItem.ToString());
}

private void buttonIgnore_Click(object sender, RoutedEventArgs e)
{
    // ignore the current misspelled word
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Ignore();
}

private void buttonDelete_Click(object sender, RoutedEventArgs e)
{
    // delete the current misspelled word
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Delete();
}
Private Sub buttonChange_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' change the current misspelled word with the suggestion selected in the ListBox
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Change(listBoxSuggestions.SelectedItem.ToString)
End Sub

Private Sub buttonIgnore_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' ignore the current misspelled word
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Ignore()
End Sub

Private Sub buttonDelete_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' delete the current misspelled word
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Delete()
End Sub

2. The TextControl_Loaded event, where the SpellingCorrectionUIProvider class is connected to the TextControl. Furthermore a StateManaging_PropertyChanged event is defined to detect whether a misspelled word is currently available or not.

private void textControl1_Loaded(object sender, RoutedEventArgs e)
{
    ...
    // attach an event to the property changed event
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(StateManaging_PropertyChanged);
    // connect the TextControl to the TX Spell correction user interface manager
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.SetCurrent(textControl1);
    ...
}

private void StateManaging_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    // select the misspelled word in the TextControl
    if (e.PropertyName == "CurrentWordToCorrect")
    {
        if (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect != null)
        {
            ((TXTextControl.MisspelledWord)txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect).Select();
        }
        else {
            // if no misspelled word is available select nothing
            textControl1.Select(0, 0);
        }
    }
}
Private Sub textControl1_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ...
    ' attach an event to the property changed event
    AddHandler txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.PropertyChanged, AddressOf StateManaging_PropertyChanged
    ' connect the TextControl to the TX Spell correction user interface manager
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.SetCurrent(textControl1)
    ...
End Sub

Private Sub StateManaging_PropertyChanged(sender As Object, e As PropertyChangedEventArgs)
    ' select the misspelled word in the TextControl
    If e.PropertyName = "CurrentWordToCorrect" Then
        If txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect IsNot Nothing Then
            DirectCast(txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect, TXTextControl.MisspelledWord).[Select]()
        Else
            ' if no misspelled word is available select nothing
            textControl1.[Select](0, 0)
        End If
    End If
End Sub

Compared to SpellingCorrectionUIProvider Simple, four new features are added to the SpellingCorrectionUIProvider Advanced sample project:

The source code is contained in the following directories:

  • %USERPROFILE%\My Documents\TX Spell 7.0.NET for WPF\Samples\WPF\CSharp\TextControl\SpellingCorrectionUIProvider\SpellingCorrectionUIProvider Advanced
  • %USERPROFILE%\My Documents\TX Spell 7.0.NET for WPF\Samples\WPF\VB.NET\TextControl\SpellingCorrectionUIProvider\SpellingCorrectionUIProvider Advanced

Correcting All Matches of the Current Misspelled Word

There are three new buttons to correct the current misspelled word and all of its occurrences: The 'Change All', 'Ignore All' and 'Add To Dict.' button. As previously described in Simple spelling correction user interface, the IsEnabled states of these Buttons are also bound inside the XAML code and the corresponding methods are handled by the Button's Click events.

Relevant API Links

<Button Name="buttonChangeAll"  VerticalAlignment="Top" Grid.Row="1" Margin="7" Content="Change All"
    Click="buttonChangeAll_Click"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsChangeAllEnabled}">
</Button>

<Button Name="buttonIgnoreAll" VerticalAlignment="Top" Grid.Column="1" Grid.Row="1" Margin="7" Content="Ignore All"
    Click="buttonIgnoreAll_Click"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsIgnoreAllEnabled}">
</Button>

<Button Name="buttonAddToDict" VerticalAlignment="Top" Grid.Column="2" Grid.Row="1" Margin="7" Content="Add To Dict."
    Click="buttonDelete_Click"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsAddToDictionaryEnabled}">
</Button>
private void buttonChangeAll_Click(object sender, RoutedEventArgs e)
{
    ...
    // change the current misspelled word and all accordances with the suggestion selected in the ListBox
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.ChangeAll(listBoxSuggestions.SelectedItem.ToString());
    ...
}

private void buttonIgnoreAll_Click(object sender, RoutedEventArgs e)
{
    // ignore the current misspelled word and all accordances
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.IgnoreAll();
}

private void buttonAddToDict_Click(object sender, RoutedEventArgs e)
{
    // add the current misspelled word to a user dictionary
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.AddToDictionary();
}
Private Sub buttonChangeAll_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ...
    ' change the current misspelled word and all accordances with the suggestion selected in the ListBox
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.ChangeAll(listBoxSuggestions.SelectedItem.ToString)
    ...
End Sub

Private Sub buttonIgnoreAll_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
     ' ignore the current misspelled word and all accordances
    txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.IgnoreAll()
End Sub

Private Sub buttonAddToDict_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' add the current misspelled word to a user dictionary
     txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.AddToDictionary()
End Sub

Selecting a Dictionary to Create Suggestions

In some cases, it is necessary to use more than one dictionary to correct a text. To provide suggestions of one or more specific dictionaries, the user can set the corresponding dictionaries by using the properties of the SuggestionDictionariesHandler class. The recommended way to handle these kind of operations is first getting those dictionaries where the language matches the language of the current misspelled word by calling the SuggestionDictionariesHandler.SuggestionDictionaries property and then adding one or more of these dictionaries to the SuggestionDictionariesHandler.SelectedSuggestionDictionaries property. If this operation causes the creation of new suggestions and the SuggestionsHandler.Suggestions property is bound to a ListBox (see Simple spelling correction user interface), the property and the suggestion ListBox are updated automatically.

In this example, the available suggestion dictionaries are provided by a ComboBox where the DataSource property is bound to the SuggestionDictionariesHandler.SuggestionDictionaries property. Additionally, the ComboBox's IsEnabled state is bound to the SuggestionDictionariesHandler.IsSuggestionDictionariesEnabled property. If the user changes the selected suggestion dictionary, the corresponding SelectionChanged event adds the new dictionary to the SuggestionDictionariesHandler.SelectedSuggestionDictionaries property.

Relevant API Links

<ComboBox Name="comboBoxSuggestionDictionaries" Grid.ColumnSpan="3" Grid.Row="3" Margin="3"
    SelectionChanged="comboBoxSuggestionDictionaries_SelectionChanged"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1},Path=SpellingCorrectionUIProvider.SuggestionDictionariesHandling.IsSuggestionDictionariesEnabled}"
    ItemsSource="{Binding Source={StaticResource txSpellChecker1},Path=SpellingCorrectionUIProvider.SuggestionDictionariesHandling.SuggestionDictionaries}" SelectedIndex="0">
</ComboBox>
private void comboBoxSuggestionDictionaries_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // Sets the current suggestion dictionaries combo box's selected dictionary as selected dictionary to use for creating suggestions
    txSpellChecker1.SpellingCorrectionUIProvider.SuggestionDictionariesHandling.SelectedSuggestionDictionaries = new TXTextControl.Proofing.Dictionary[] { (TXTextControl.Proofing.Dictionary)comboBoxSuggestionDictionaries.SelectedItem };
    listBoxSuggestions.SelectedIndex = 0;
}
Private Sub comboBoxSuggestionDictionaries_SelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
    ' Sets the current suggestion dictionaries combo box's selected dictionary as selected dictionary to use for creating suggestions
    txSpellChecker1.SpellingCorrectionUIProvider.SuggestionDictionariesHandling.SelectedSuggestionDictionaries = New TXTextControl.Proofing.Dictionary() {DirectCast(comboBoxSuggestionDictionaries.SelectedItem, TXTextControl.Proofing.Dictionary)}
    listBoxSuggestions.SelectedIndex = 0
End Sub

Displaying the Sentence Where the Misspelled Word Is Located

Determining the sentence where the current misspelled word is located could be helpful to correct the word depending on its surrounding. For these cases the PreviewHandler.PreviewSentenceBounds property provides the index and the length of the misspelled word's sentence.

Applied to our example, the sentence extraction is handled by a class that is derived from the System.Windows.Data.IValueConverter interface. An instance of this converter is used for the Binding between the TextBlock.Text property and the PreviewHandler.PreviewSentenceBounds property. Consequently, on every PreviewSentenceBounds property change, the converter determines the misspelled word's sentence text and commits it to the TextBlock.Text property.

Relevant API Links

<TextBlock Name="textBoxSentence" Grid.ColumnSpan="4" Grid.Row="1" Height="50" Margin="3,0" VerticalAlignment="Top"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1},Path=SpellingCorrectionUIProvider.PreviewHandling.IsPreviewSentenceBoundsEnabled}"
    Text="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.PreviewHandling.PreviewSentenceBounds,Converter={StaticResource previewBoundsConverter},ConverterParameter={StaticResource txSpellChecker1}}">
</TextBlock>
public class PreviewBoundsConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        if (value != null &amp;&amp;  parameter != null) {
            return GetMisspelledWordSentence((TXSpellChecker)parameter, (int[])value);
        }
        else {
            return "";
        }
    }

    // returns the sentence of the current word to correct.
    private string GetMisspelledWordSentence(TXSpellChecker p_txsSpellChecker, int[] p_riPreviewSentenceBounds) {
        TXTextControl.IFormattedText iftCurrentTextPart = (TXTextControl.IFormattedText)p_txsSpellChecker.SpellingCorrectionUIProvider.StateManaging.CurrentIFormattedText;
        TXTextControl.Paragraph pgMisspelledWordsParagraph = iftCurrentTextPart.Paragraphs.GetItem(((TXTextControl.MisspelledWord)p_txsSpellChecker.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect).Start);
        return pgMisspelledWordsParagraph.Text.Substring(p_riPreviewSentenceBounds[0] - (pgMisspelledWordsParagraph.Start - 1), p_riPreviewSentenceBounds[1]);
    }
}
Public Class PreviewBoundsConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
        If value IsNot Nothing AndAlso parameter IsNot Nothing Then
            Return GetMisspelledWordSentence(DirectCast(parameter, TXSpellChecker), DirectCast(value, Integer()))
        Else
            Return ""
        End If
    End Function

    ' returns the sentence of the current word to correct.
    Private Function GetMisspelledWordSentence(ByVal p_txsSpellChecker As TXSpellChecker, ByVal p_riPreviewSentenceBounds As Integer()) As String
        Dim iftCurrentTextPart As TXTextControl.IFormattedText = DirectCast(p_txsSpellChecker.SpellingCorrectionUIProvider.StateManaging.CurrentIFormattedText, TXTextControl.IFormattedText)
        Dim pgMisspelledWordsParagraph As TXTextControl.Paragraph = iftCurrentTextPart.Paragraphs.GetItem(DirectCast(p_txsSpellChecker.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect, TXTextControl.MisspelledWord).Start)
        Return pgMisspelledWordsParagraph.Text.Substring(p_riPreviewSentenceBounds(0) - (pgMisspelledWordsParagraph.Start - 1), p_riPreviewSentenceBounds(1))
    End Function
End Class

Setting a Suggestion Manually to Correct the Current Misspelled Word

Sometimes, no suggestions can be created for a misspelled word. In this case, the user needs an interface to correct the word manually.

The SpellingCorrectionUIProvider Advanced sample project provides a TextBox to give the user the option to edit the current misspelled word which is updated inside the box on every CurrentWordToCorrect property change. The edited word is applied when the user clicks the 'Change' or 'Change All' button.

Relevant API Links

<TextBox Grid.ColumnSpan="3" Grid.Row="3" Margin="3,0" Name="textBoxEdit" VerticalAlignment="Top" Width="180"
    Text="{Binding Source={StaticResource txSpellChecker1},Mode=OneWay, Path=SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect,Converter={StaticResource wordToCorrectConverter},NotifyOnTargetUpdated =True}"
    TextChanged="textBoxEdit_TextChanged" PreviewKeyDown="textBoxEdit_PreviewKeyDown" TargetUpdated="textBoxEdit_TargetUpdated">
</TextBox>
public class MisspelledWordConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        MisspelledWord mwWordToCorrect = (MisspelledWord)value;
        if (mwWordToCorrect == null) {
            return "";
        }
        else {
            return mwWordToCorrect.Text;
        }
    }
}

private void buttonChange_Click(object sender, RoutedEventArgs e)
{
    if (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.IsWordToCorrectEditing)
    {
        // change the current misspelled word with the text box' text.
        txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Change(textBoxEdit.Text);
    }
    else {
        // change the current misspelled word with the suggestion selected in the ListBox
        txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Change(listBoxSuggestions.SelectedItem.ToString());
    }
}
Public Class MisspelledWordConverter
    Implements IValueConverter

    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
        Dim mwWordToCorrect As MisspelledWord = DirectCast(value, MisspelledWord)
        If mwWordToCorrect Is Nothing Then
            Return ""
        Else
            Return mwWordToCorrect.Text
        End If
    End Function
End Class

Private Sub buttonChange_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    If txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.IsWordToCorrectEditing Then
        ' change the current misspelled word with the text box' text.
        txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Change(textBoxEdit.Text)
    Else
        ' change the current misspelled word with the suggestion selected in the ListBox
        txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.Change(listBoxSuggestions.SelectedItem.ToString)
    End If
End Sub

Additionally, the TextBox's TextChanged event calls the CorrectionHandler.CheckCorrectedWord method to check whether the edited TextBox' text is correct or not.

Relevant API Links

private void textBoxEdit_TextChanged(object sender, TextChangedEventArgs e)
{
    if (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.Mode != TXTextControl.Proofing.TXSpell.SpellingCorrectionMode.WordToCorrectIsDuplicate)
    {
        if (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.Mode != TXTextControl.Proofing.TXSpell.SpellingCorrectionMode.CorrectionCompleted)
        {
            string message;
            if (txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.CheckCorrectedWord(textBoxEdit.Text, out message))
            {
                // ... do something to show that the text box's text is correct
            }
            else
            {
                // ... do something to show that the text box's text is still incorrect
            }
        }
        else
        {
            // ... the spelling correction is completed. There is no text to check for correctness
        }
    }
}
Private Sub textBoxEdit_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
    If (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.Mode &lt;&gt; TXTextControl.Proofing.TXSpell.SpellingCorrectionMode.WordToCorrectIsDuplicate) Then
        If (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.Mode &lt;&gt; TXTextControl.Proofing.TXSpell.SpellingCorrectionMode.CorrectionCompleted) Then
            Dim message As String = String.Empty
            If txSpellChecker1.SpellingCorrectionUIProvider.CorrectionHandling.CheckCorrectedWord(textBoxEdit.Text, message) Then
                ' ... do something to show that the text box's text is correct
            Else
                ' ... do something to show that the text box's text is still incorrect
            End If
        Else
            ' ... the spelling correction is completed. There is no text to check for correctness
        End If
    End If
End Sub

To inform the SpellingCorrectionUIProvider that the user is currently editing the word manually, the StateManager.IsWordToCorrectEditing property is set to true on the first editing operation. To leave the editing mode, the user can press the 'Undo Edit' button where the Proofing.SpellingCorrectionUIProvider.StateManager.IsWordToCorrectEditing property is set to false.

Relevant API Links

<Button Name="buttonUndoEdit" VerticalAlignment="Top" Grid.Column="3" Grid.Row="3" Margin="0,0,3,0" Content="Undo Edit"
    IsEnabled="{Binding Source={StaticResource txSpellChecker1}, Path=SpellingCorrectionUIProvider.CorrectionHandling.IsUndoEditEnabled}"
    Click="buttonUndoEdit_Click">
</Button>
private void textBoxEdit_PreviewKeyDown(object sender, KeyEventArgs e)
{
    // start word editing
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.IsWordToCorrectEditing = true;
}

private void buttonUndoEdit_Click(object sender, RoutedEventArgs e)
{
    // abort word editing
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.IsWordToCorrectEditing = false;
    textBoxEdit.Text = ((TXTextControl.MisspelledWord)txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect).Text;
    buttonIgnore.Focus();
}
Private Sub textBoxEdit_PreviewKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
    ' start word editing
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.IsWordToCorrectEditing = true
End Sub

Private Sub buttonUndoEdit_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' abort word editing
    txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.IsWordToCorrectEditing = false
    textBoxEdit.Text = CType(txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.CurrentWordToCorrect,TXTextControl.MisspelledWord).Text
    buttonIgnore.Focus()
End Sub

The sample project Custom SpellCheckDialog shows how to create a fully operational spell check dialog. Its functionality is completely based on the SpellingCorrectionUIProvider methods and properties that were introduced by the previous articles Simple spelling correction user interface and Advanced spelling correction user interface.

The major differences to these samples lie in connecting the TextControl before opening the dialog, handling a preview where to correct manually the current misspelled word, changing the functionality of a button depending on the StateManager.Mode and implementing a Button to open the OptionsDialog.

In the following, the underlying concepts behind these issues are described, but it won't give any further explanation in code details. Therefore, we ask you to explore the Custom SpellCheckDialog sample more closely by yourself.

Connecting the TextControl Before Opening the Dialog

The principal task of a spell check dialog is to correct the current misspelled words one by one with a correction supporting user interface. But opening such a dialog makes only sense, if the TextControl actually contains misspelled words. To prevent an unnecessary initializing of the spell check dialog, the TextControl should be first connected with the SpellingCorrectionUIProvider to determine its <mode. If it is set to SpellingCorrectionMode.NoWordsToCorrectFound, the dialog won't be opened and a MessageBox informs the user that the TextControl does not contain any misspelled words. Whether or not the dialog is shown, the SpellingCorrectionUIProvider should be reset to its initial state by using the StateManager Class method.

Handling a Preview

Most spell check dialogs provide a preview that gives the user an opportunity to correct the current misspelled word manually. Such an editor usually shows the sentence where the misspelled word is located and highlights it in red color. Additionally, on starting editing inside the preview, the rest of the dialog changes to an editing mode, where most buttons and controls are disabled and the 'Ignore' button is changed to an 'Undo Edit' button.

To implement this behavior, the SpellingCorrectionUIProvider provides the StateManager.IsWordToCorrectEditing property that changes the current mode to SpellingCorrectionMode.WordToCorrectEditing. In this case, bound Button's and Control's are disabled, except the 'Change' and 'Change All' buttons. However, in this example, the Clicked events of these two buttons won't commit the selected suggestion of the suggestion ListBox anymore, but the modified misspelled word from the preview editor as the change parameter. Furthermore, to give the user the chance to cancel misspelled word editing using the preview, the 'Ignore' button is changed to an 'Undo Edit' button, where its Clicked event sets the StateManager.IsWordToCorrectEditing Property to false. The preview itself is updated on every current misspelled word change or use of the 'Undo Edit' button.

Changing the Functionality of a Button

There are two cases where the functionality of a button can be changed. The first one, as described above, is when the 'Ignore' needs to be an 'Undo Edit' button. The other one is when the misspelled word is a duplicated word. In this case, the 'Change' button becomes a 'Delete' button and its Clicked event calls the CorrectionHandler.Delete method instead the CorrectionHandler.Change method.

Open an OptionsDialog

In most spell check dialogs, the user can change some spelling settings, by opening an options dialog. To adopt any changes by these modifications, the connected TextControl must be spell checked again on closing the options dialog. The StateManager.IsOptionsSettings property supports that behavior: Before opening the options dialog, it must be set to true, to save any prior ignore operations. When the dialog is closed, the property is set to false, which leads to a spell check of the TextControl and a resetting of the stored, ignored words.