#c_sharp #wpf #webbrowser
У меня нет потребности использовать WebBrowser в XAML, мне он нужен всего лишь для того что бы иметь возможность вызвать событие Click на одном из тегов загруженной HTML страницы. Я не могу вызывать событие Click на нужном мне теге, до того как загрузиться страница. Для того что бы получить уведомление о загрузке страницы мне нужно подписаться на событие LoadCompleted. Но, судя из того что я вижу событие LoadCompleted не генерируется пока WebBrowser не будет добавлен в XAML. По причине того что я хочу осуществлять загрузку множества HTML страниц параллельно, перспектива постоянно добавлять WebBrowser контрол в разметку XAML до загрузки одной из множества страниц и удаление его из этой разметки после загрузки нужной страницы выглядит не очень удобно. Моя цель получить доступ к вызову события Click на загруженной HTML странице без возни с ХАМL. Можно ли получить доступ к событию LoadCompleted контрола WebBrowser без его привязки к XAML. Возможно ли это? Может быть есть какой то другой путь? Код отражающий суть проблемы (WebBrowser в XAML не добавлялся) public partial class SettingsWindow : Window { private WebBrowser browser = new WebBrowser(); public SettingsWindow() { InitializeComponent(); this.browser.LoadCompleted += Browser_LoadCompleted; this.browser.Source = new Uri(@"https://www.google.com.ua/"); //this.browser.Navigate(path); <-- пробовал загружать страницу и этим способом. } private void Browser_LoadCompleted(object sender, NavigationEventArgs e) { // Этот обработчик никогда не вызывается если объект WebBrowser не // добавлен в XAML или не добавлен программным путем в качестве // дочернего компонента к одному из существующих контролов окна. } }
Ответы
Ответ 1
Действительно, событие LoadCompleted для WPF WebBrowser не вызывается до тех пор, пока он не добавлен в какое-либо отображаемое окно или элемент управления, это известная проблема. Причина ее в том, как WebBrowser осуществляет инициализацию своего внутреннего ActiveX-элемента Internet Explorer, который и занимается загрузкой страницы. Это можно понять, посмотрев в его исходный код на Reference Source. Для корректной работы события DocumentCompleted внутреннего ActiveX-объекта класс ActiveXHost должен быть переведен в состояние ActiveXState.InPlaceActive. По умолчанию он находится в ActiveXState.Running (см. инициализацию свойства), переход в состояние InPlaceActive происходит при вызове метода BuildWindowCore, который вызывается только при отображении родительского окна элемента. Это поведение отличается от аналогичного элемента в WinForms, который сразу переводится в InPlaceActive при инициализации, см. здесь). Решение 1 - Использование WinForms WebBrowser Элемент WebBrowser в WinForms избавлен от этой проблемы (аналогичное событие DocumentCompleted всегда вызывается), и функционально ни в чем не уступает элементу из WPF. Можно просто добавить ссылку на System.Windows.Forms и использовать его. Решение 2 - Использование окна за пределами экрана Для вызова BuildWindowCore требуется видимое окно, однако никто не запрещает сделать координаты отрицательными и поместить окно за пределы экрана: Window wnd = new Window(); wnd.Content = browser; wnd.ShowInTaskbar = false; wnd.Top = -1000; wnd.Left = -1000; wnd.Width = 0; wnd.Height = 0; wnd.Show(); Решение 3 - Грязный хак с использованием отражения Просто вызвать внутренний метод TransitionUpTo, передав в качества аргумента константу InPlaceActive (4): using System.Reflection; const int InPlaceActive = 4; //... var method = browser.GetType().GetMethod("TransitionUpTo",BindingFlags.NonPublic | BindingFlags.Instance); method.Invoke(browser, new object[] {InPlaceActive});
Комментариев нет:
Отправить комментарий