I try to enable spell check for the CefSharp Chromium embedded browser (v3.3396.1786 installed with NuGet) and the CefSharp.WPF component (v67). I can get spell check to work with a single language but I'm not able to change the dictionary for spellchecking at runtime. I tried the examples shown and linked on CefSharps github page but without success.
My CefSharp browser always uses the the Locale to determine the language to use for spell checking no matter what I set with RequestContext.SetPreference()
This is my code which initializes Cef:
public static void Initialize()
{
var settings = new CefSettings
{
BrowserSubprocessPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
Environment.Is64BitProcess ? "x64" : "x86",
"CefSharp.BrowserSubprocess.exe"),
Locale = "de-DE",
RemoteDebuggingPort = 8088,
};
// Set BrowserSubProcessPath based on app bitness at runtime
// Make sure you set performDependencyCheck false
Cef.Initialize
(
settings,
performDependencyCheck: false,
browserProcessHandler: null
);
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
}
The actual browser is set up and created in another method:
private void create_web_browser()
{
current_web_browser = new ChromiumWebBrowser
{
Visibility = Visibility.Hidden,
BrowserSettings = new BrowserSettings
{
FileAccessFromFileUrls = CefState.Enabled,
UniversalAccessFromFileUrls = CefState.Enabled,
Javascript = CefState.Enabled,
ImageLoading = CefState.Enabled,
JavascriptAccessClipboard = CefState.Enabled,
JavascriptCloseWindows = CefState.Enabled,
JavascriptDomPaste = CefState.Enabled
}
};
current_helper = new ChromiumObjectForScriptingHelper(web_browser_ready_async, current_web_browser);
if (ToolbarConfig != null)
{
current_helper.SetToolbarConfig(ToolbarConfig);
}
current_web_browser.RegisterJsObject("callbackObj", current_helper);
var cur_dir = Directory.GetCurrentDirectory();
var url = $"file://{cur_dir}/ckeditor/editor.html";
current_web_browser.Address = url;
current_web_browser.RequestContext = new RequestContext();
current_web_browser.RequestContext.SetPreference("browser.enable_spellchecking", true, out _);
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<string> { "en-US" }, out _);
grid.Children.Add(current_web_browser);
}
An additional method is used to enable the user to change language later:
public void SetSpellcheck(Spellcheck language)
{
if (language == Spellcheck.None) return;
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<string> { get_locale_for_language(language) }, out _);
}
As you can see I try to set the spell checking settings but no matter what I set there, it has no effect. I could set enable_spellcheck
to false and it still checks the spelling and the dictionaries I set are also ignored. Instead of what I put in dictionaries, the language previously set in Locale
will be used. (I checked the out variable but there were no errors)
I also tried using the global RequestContext but with no success.
Apparently other people got it to work somehow so I'm feeling like I miss something important here, or doing something completely stupid.
Another thing is that, if I use GetAllPreferences(true)
, to get a list of all the settings with defaults, I just get null
.
Thanks to @amaitlands's comments I now know that the issue was that I was setting the preferences in the wrong thread. I had the misconception that CefSharp was running in my applications UI-Thread, when it actually was running in its own.
The solution is to use Cef.UIThreadTaskFactory.StartNew()
to run the code inside of the CefSharp UI-Thread
Cef.UIThreadTaskFactory.StartNew(delegate
{
current_web_browser.RequestContext.SetPreference("browser.enable_spellchecking", true, out _);
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<object> { "en-US" }, out _);
});
I also had to change the type of the List<>
to object
since I'm using an older version of CefSharp.WPF otherwise I'd get a Trying to set a preference of type LIST to value of type NULL
error.