При использовании JavaScript в .NET объекте WebBrowser нужно учитывать некоторые ньюансы, связанные с загрузкой страницы. Для того, чтобы выполнить какой-то JavaScript — код необходимо проверить загрузку страницы. Простое решение — это использование в C# специального слушателя события — WebBrowser.DocumentCompleted, который вызывается, когда страница полностью загружена.
Пример вызовава JavaScript — кода из C#
Ниже дан пример его использования. Пусть у нас есть HTML сраница index.html со следующим JavaScript — методом, который определен в head
<script> function runScript(){ alert("Hello World!"); } </script>
Тогда вызов данного метода через C# будет выглядеть вот так
public MyForm() { //... //Сначала определяем новое событие для браузера и передаем имя обработчика string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase); webBrowser.Url = new Uri(Path.Combine(appDir, @"pages\index.html")); webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(runWebScripts); } //Далее, в классе определяем новый обработчик void runWebScripts(object sender, WebBrowserDocumentCompletedEventArgs e) { webBrowser.Document.InvokeScript("runScript", new object[] { }); }
Пример создания JavaScript — кода и его запуска из C#
Теперь посмотрим как создать новый элемент в DOM через C# и создать в нем код JavaScript
public MyForm() { //... //Сначала определяем новое событие для браузера и передаем имя обработчика string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase); webBrowser.Url = new Uri(Path.Combine(appDir, @"pages\index.html")); webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(runWebScripts); } //Далее, в классе определяем новый обработчик void runWebScripts(object sender, WebBrowserDocumentCompletedEventArgs e) { HtmlDocument doc = webBrowser.Document; HtmlElement head = doc.GetElementsByTagName("head")[0]; HtmlElement s = doc.CreateElement("script"); s.SetAttribute("text", "function sayHello() { alert('hello'); }"); head.AppendChild(s); webBrowser.Document.InvokeScript("sayHello"); }
Мы добаляем в тег head новый элемент script и устанавливаем в качестве его атрибута text JavaScript — код и далее вызываем этот код с помощью метода InvokeScript
Подключение jQuery в WebBrowser через C# в виде гиперссылки
Давайте посмотрим, как использовать библиотеку jQuery в своем проекте на C#. Для этого нам необходимо создать новый элемент script и передать в атрибут src значение ссылки, для примера подключим библиотеку из стандартной ссылки Google
public MyForm() { //... //Сначала определяем новое событие для браузера и передаем имя обработчика string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase); webBrowser.Url = new Uri(Path.Combine(appDir, @"pages\index.html")); webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(runWebScripts); } //Далее, в классе определяем новый обработчик void runWebScripts(object sender, WebBrowserDocumentCompletedEventArgs e) { //Получаем доступ к тегу head HtmlDocument doc = webBrowser.Document; HtmlElement head = doc.GetElementsByTagName("head")[0]; //Подключаем библиотеку HtmlElement jQuery = doc.CreateElement("script"); jQuery.SetAttribute("src", "http://code.jquery.com/jquery-latest.min.js"); head.AppendChild(jQuery); //Далее запускаем код, содержащий jQuery HtmlElement script = doc.CreateElement("script"); script.SetAttribute("text", "function setRedColor() { $('body').css({ 'background-color': 'red' }); }"); head.AppendChild(script); //Вызываем метод, содержащий код jQuery webBrowser.Document.InvokeScript("setRedColor"); }
Подобным образом можно подключить не только jQuery библиотеку, но и любой удаленный JavaScript файл.
Подключение jQuery в WebBrowser через C# из локального хранилища
Если нам необходимо подгрузить jQuery или любой JavaScript — файл локально, то тут необходимо учитывать некоторые особенности, связанные с jQuery, так как при локальном подключении у вас может выскочить ошибка такого рода: Object doesn’t support property or method ‘defineProperty’, который означает: Объект не поддерживает свойство или метод ‘defineProperty’. Что непонятно, так это то, что при подключении через удаленную гиперссылку эта ошибка не выводиться и браузер работает нормально. Данная ошибка актуальная для версий IE 10 — 11 и выше, возможно. В IE он поддерживается, а в IE 8 — ограниченно. Решением данной проблемы является использование тегов для переключения браузера в режимы совместимости с ранними версиями. Подробно про это написано в официальной статье Microsoft «Specifying legacy document modes»
Из данной статьи следует, что для совместимости нужно использовать мета — тег
<meta http-equiv="x-ua-compatible" content="IE=edge" />
Запись атрибута content дает указание на то, с какой версией IE следует иметь совместимость. В нашем случае, данная запись эквивалентна использованию типа документа HTML5 и совместимости с другими браузерами. Это заставит Internet Explorer работать в режиме последней поддерживаемой спецификации документа. Значение «IE=edge» является наиболее полезным для регулярного поддерживания веб-сайтов, которые отрабатываются на совместимость между несколькими браузерами, в том числе Internet Explorer.
Данный тег совместимости необходимо в начале тега head в документе.
Итак, теперь, собственно сам код подключения. HTML документ будет таким
... <head> <meta http-equiv="x-ua-compatible" content="IE=edge" /> </head> ...
C# — код будет таким
HtmlDocument doc = wbTestEditor.Document; HtmlElement head = doc.GetElementsByTagName("head")[0]; HtmlElement s = doc.CreateElement("script"); s.SetAttribute("src", Environment.CurrentDirectory + @"\pages\js\jquery-2.1.3.min.js"); head.AppendChild(s);
Свойство Environment.CurrentDirectory содержит корневую папку запускаемой программы, а @ нужен для обработки слэшей в нормальном виде, чтобы не писать как \\. Environment.CurrentDirectory — это тоже самое, если бы мы писали как Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase), но в коротком виде.