Advanced spelling correction user interface

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

The source code is contained in the following directories:

Correcting all matches of the current misspelled word by using the ChangeAll, IgnoreAll and AddToDicionary methods:

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>

[C#]
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();
}
[Visual Basic]
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>
[C#]
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;
}
[Visual Basic]
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>
[C#]
public class PreviewBoundsConverter : IValueConverter
{
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
		if (value != null &&  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]);
	}
}
[Visual Basic]
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 StateManager.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>
[C#]
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());
	}
}
[Visual Basic]
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:

[C#]
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
		}
	}
}
[Visual Basic]
Private Sub textBoxEdit_TextChanged(ByVal sender As Object, ByVal e As TextChangedEventArgs)
	If (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.Mode <> TXTextControl.Proofing.TXSpell.SpellingCorrectionMode.WordToCorrectIsDuplicate) Then
		If (txSpellChecker1.SpellingCorrectionUIProvider.StateManaging.Mode <> 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>
[C#]
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();
}
[Visual Basic]
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