TX Spell .NET for Windows Forms

Loading and Managing Dictionaries

Topic

Every check of TX Spell .NET runs against the dictionaries in one collection. Which dictionaries it holds decides what is correct: English only by default, English and German once you add the German dictionary, or a specialist vocabulary on top. Here is where the spell checker finds dictionary files, which one it loads by itself, and how your code adds, switches off and removes dictionaries while the application runs.

Where the Spell Checker Finds Dictionaries

TX Spell .NET looks for dictionary files in its default dictionary folder, the folder Dictionaries next to the application or, on the development machine, below the Assembly folder of the installation. Both places are what the default of DictionariesDirectoryPath, "(Auto)", stands for; Installing Dictionaries and Language Data shows how to use another folder.

Which Dictionary Is Loaded First

The Language property of the spell checker chooses the dictionary it loads by itself, the default dictionary. Its value is "(Auto)" when you drop a TXSpellChecker on a form:

  1. The spell checker loads the dictionary of the language the application runs in, if the default folder has it.
  2. Otherwise it loads a dictionary of a close language: in a British English environment with only en_US.dic and de_DE_frami.dic in the folder, it takes en_US.dic.
  3. Otherwise it loads en_US.dic, and if that is missing too, the first dictionary in the folder.

To fix the default dictionary instead, set Language to the file name of a dictionary in the default folder, in the Properties window or in code:

// Use the German dictionary as the default dictionary
txSpellChecker1.Language = "de_DE_frami.dic";

A value ending in .txd loads a user dictionary instead, and "(none)" loads no dictionary at all, for an application that adds only dictionaries of its own. The chosen dictionary has its IsSelectedAsDefault property set to true.

See Which Dictionaries Are There

Two properties answer the two questions a program asks:

  • AvailableDictionaries is an array of the file names in the default folder, whether they are loaded or not, such as de_DE_frami.dic and en_US.dic. It is the list to offer in a language menu of your application.
  • Dictionaries is the DictionaryCollection of the dictionaries that are loaded and used.

Each entry of Dictionaries is a Dictionary: an OpenOfficeDictionary for a Hunspell dictionary, or a UserDictionary for a word list of your own. These properties describe it:

PropertyHolds
NameThe file name, such as en_US.dic
DisplayNameThe name the dialogs show; by default the file name
LanguageThe language, taken from the file name, such as German (Germany) for de_DE_frami.dic; null when the name carries none
IsSpellCheckingEnabledWhether words are checked against it; true by default
IsGetSuggestionsEnabledWhether it provides suggestions; true by default
DictionaryEncodingThe encoding of the dictionary, a System.Text.Encoding

Add a Dictionary

Copy the files of the dictionary into the default folder, as Hunspell and OpenOffice Dictionaries describes. Then create an OpenOfficeDictionary with the file name and add it with Add, for example when the form loads:

using System;
using System.Windows.Forms;
using TXTextControl.Proofing;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Load += Form1_Load;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // Check German text as well as English text
        OpenOfficeDictionary german = new OpenOfficeDictionary("de_DE_frami.dic");
        txSpellChecker1.Dictionaries.Add(german);
    }
}

The code works as follows:

  • The constructor takes the name of the .dic or .aff file. A name without a path refers to the default folder. The file is read only when the dictionary is added to the collection.
  • Add loads the dictionary, checks that it is valid, and returns its index in the collection.
  • The new dictionary gets its language from its file name, here German (Germany).

From now on, a word is correct if one of the enabled dictionaries knows it. In a test with the sentence This sentense has a mistake. Dieser Satz hat einen Fehlr., English alone reports sentense, Dieser, Satz, einen and Fehlr; with the German dictionary added, only sentense and Fehlr remain.

To check a text in one language only, pass the language to Check, as Check a String in One Language shows.

Check While a Large Dictionary Loads

By default, Add loads a dictionary completely before the spell checker uses it. LoadDictionaryDelayed of the DictionaryCollection changes this: set to true, it loads dictionaries partially when they are added, and the spell checker checks text while the rest is still loading:

// Check text while the German dictionary is still loading
txSpellChecker1.Dictionaries.LoadDictionaryDelayed = true;
txSpellChecker1.Dictionaries.Add(new OpenOfficeDictionary("de_DE_frami.dic"));

The dictionary is loaded when it is added, so set the property before Add. The price is speed: until the dictionary is loaded completely, checking is slower than with a fully loaded one. For the full checking speed, leave the property at its default, false.

Load a Dictionary From Memory

A dictionary doesn't have to be a file in a folder. A second constructor takes the lines of the .dic and the .aff file as string arrays, together with the language, so the dictionary can come from a database or from resources embedded in your assembly:

using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using TXTextControl.Proofing;

private static string[] ReadLines(string resourceName, Encoding encoding)
{
    List<string> lines = new List<string>();

    using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
    using (StreamReader reader = new StreamReader(stream, encoding))
    {
        string line;
        while ((line = reader.ReadLine()) != null)
        {
            lines.Add(line);
        }
    }

    return lines.ToArray();
}

private void AddEmbeddedDictionary()
{
    // The German files are encoded in ISO-8859-1, as the SET line of the .aff file says
    Encoding encoding = Encoding.GetEncoding("ISO-8859-1");

    // The resource names depend on the default namespace and the folder of the files
    OpenOfficeDictionary german = new OpenOfficeDictionary(
        ReadLines("MyApp.Dictionaries.de_DE_frami.dic", encoding),
        ReadLines("MyApp.Dictionaries.de_DE_frami.aff", encoding),
        new CultureInfo("de-DE"));

    txSpellChecker1.Dictionaries.Add(german);
}

Add the two files to the project with the build action Embedded Resource. Read them with the encoding that the SET line of the .aff file names: SET ISO8859-1 for the German dictionary, SET UTF-8 for the English one. The blog article TX Spell .NET 3.0: Loading Dictionaries from Embedded Resources describes the approach.

Switch Off or Remove a Dictionary

A dictionary can stay loaded but play a smaller part:

  • Set IsSpellCheckingEnabled to false, and the dictionary no longer decides whether a word is correct, but can still provide suggestions.
  • Set IsGetSuggestionsEnabled to false, and it checks words but provides no suggestions.

To take a dictionary out entirely, find it with GetItem and pass it to Remove:

Dictionary german = txSpellChecker1.Dictionaries.GetItem("de_DE_frami.dic");

if (german != null)
{
    txSpellChecker1.Dictionaries.Remove(german);
}

GetItem takes the full name, with the extension, and returns null when there is no such dictionary. Add and Remove throw an exception while the spell check dialog is open. Only a user dictionary can be added or removed then, and only while the options dialog that the Options... button of the spell check dialog opened is shown.

React When Dictionaries Change

The spell checker raises DictionaryAdded and DictionaryRemoved whenever the collection changes, whether your code or the user made the change. The Dictionary property of the arguments is the dictionary concerned, for example to update a language menu of your application. Events lists all events.

What Users Can Do

Users see the dictionaries in the options dialog, whose tab Spell Checking Dictionaries switches each one off for spell checking or for suggestions, and in the Suggestions Dictionary list of the spell check dialog, which chooses the dictionary the suggestions come from. With the ribbon of TX Text Control, the Settings group of the Proofing tab also has a Load Dictionary button. The Spell Checking Dictionaries Tab and The Suggestions Dictionary List describe both lists, and Hide or Rename a Dictionary how to hide a dictionary from the user or give it a display name.

Next Steps