Aistis Taraskevicius
Aistis Taraskevicius

Reputation: 811

ckeditor in WPF WebBrowser Control

So I am having a nightmare trying to run ckeditor in wpf webbrowser control. Custom built ckeditor that our company is using for their websites, throws an error that points to nowhere.. line 0, yet it works everywhere else, including IE. Basic package, semi loads, but throws undefined error and stay greyed out in loading phase. This is with latest ck editor 4.7. I've tried using version 3.6 with which nothing happens at all, ckeditor throws no error, but doesnt load either ( works fine outside of wpf browser).

Here is some basic html code that I inject into the wpfbrowser.

            WebBrowser webBrowser = dependencyObject as WebBrowser;
        if (webBrowser != null)
        { 
            var html = "<head>" +

                       "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />" +
                       "<meta charset=\"UTF-8\">" +

                      // $"<script type=\"text/javascript\" src=\"{ResourceDir}MathJax\\MathJax.js?config=MML_HTMLorMML,default\"></script>" +
                       $"<script type=\"text/javascript\" src=\"{ResourceDir}ckeditor\\ckeditor.js\"></script>" +
                       $"<script type=\"text/javascript\" src=\"{ResourceDir}JavaScript\\essay.js\"></script>" +
                       // $"<link rel=\"stylesheet\" type=\"text/css\" href=\"{ResourceDir}\\CSS\\main.css\">" +

                       "</head>" +

                       "<body>" +
                       "         <form>\r\n" +
                       "            <textarea name=\"editor\" id=\"editor\" rows=\"10\" cols=\"80\">\r\n" +
                                    $"Hello World!" + /*{e.NewValue}*/
                       "            </textarea>\r\n" +
                       "        </form>"+
                       " <button onclick=\"ReplaceEditor()\">Click me</button> " +
                       "</body>";

            webBrowser.NavigateToString(html);

Other javascript such as MathJax and so on works just fine, please ignore the way I build HTML, its not relevant now.

This is essay.js content

function ReplaceEditor() {
CKEDITOR.replace('editor');
}
window.onerror = function (message, url, lineNumber) {
    window.external.GetErrors(message, url, lineNumber);
}

catching errors doesnt help much as it returns same line 0 char 0 that webbrowser throws for all errors . Any help appreciated, from what I've read it should be working as people made it work before.

Upvotes: 2

Views: 1340

Answers (1)

noseratio
noseratio

Reputation: 61666

I guess I know what's wrong, you're using NavigateToString, which produces an about:blank page. This is not going to work with CKEditor, same as a file://-based editor host page. You need a real http/https-based page, which can be as simple as referencing CKEditor from their CDN (a very reliable Amazon-hosted one):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>CKEditor</title>
        <script src="https://cdn.ckeditor.com/4.7.1/standard/ckeditor.js"></script>
    </head>
    <body>
        <textarea name="editor1"></textarea>
        <script>
            CKEDITOR.replace( 'editor1' );
        </script>
    </body>
</html>

Below is simple example loading CKEditor Standard Editor Example into a WPF WebBrowser control, it works without any issues for me.

If you can't have your own dedicated online page to host CKEditor, you might need to run an in-app single-page web server to serve it via http://localhost. There're many examples out there on how to do it (e.g. this one).

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;

namespace WpfWebEditor
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        WebBrowser _webBrowser;

        static MainWindow()
        {
            var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
            SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, GetBrowserEmulationMode());
        }

        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += MainWindow_Loaded;

            _webBrowser = new WebBrowser();
            this.Content = _webBrowser;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            _webBrowser.Navigate("https://nightly.ckeditor.com/standard/samples/");
        }

        private static void SetBrowserFeatureControlKey(string feature, string appName, uint value)
        {
            using (var key = Registry.CurrentUser.CreateSubKey(
                String.Concat(@"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
                RegistryKeyPermissionCheck.ReadWriteSubTree))
            {
                key.SetValue(appName, (UInt32)value, RegistryValueKind.DWord);
            }
        }

        private static UInt32 GetBrowserEmulationMode()
        {
            int browserVersion = 7;
            using (var ieKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer",
                RegistryKeyPermissionCheck.ReadSubTree,
                System.Security.AccessControl.RegistryRights.QueryValues))
            {
                var version = ieKey.GetValue("svcVersion");
                if (null == version)
                {
                    version = ieKey.GetValue("Version");
                    if (null == version)
                        throw new ApplicationException("Microsoft Internet Explorer is required!");
                }
                int.TryParse(version.ToString().Split('.')[0], out browserVersion);
            }

            UInt32 mode = 11000; // Internet Explorer 11. Webpages containing standards-based !DOCTYPE directives are displayed in IE11 Standards mode. Default value for Internet Explorer 11.
            switch (browserVersion)
            {
                case 7:
                    mode = 7000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control.
                    break;
                case 8:
                    mode = 8000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode. Default value for Internet Explorer 8
                    break;
                case 9:
                    mode = 9000; // Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode. Default value for Internet Explorer 9.
                    break;
                case 10:
                    mode = 10000; // Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE10 mode. Default value for Internet Explorer 10.
                    break;
                default:
                    // use IE11 mode by default
                    break;
            }

            return mode;
        }
    }
}

Upvotes: 2

Related Questions