我不需要在 XAML 中使用 WebBrowser,我只需要它能够在加载的 HTML 页面的标签之一上触发 Click 事件。
在页面加载之前,我无法在我想要的标签上触发 Click 事件。为了接收页面加载通知,我需要订阅 LoadCompleted 事件。但据我所知,在将 WebBrowser 添加到 XAML 之前,不会触发 LoadCompleted 事件。
因为我想并行加载许多 HTML 页面,所以在加载多个页面之一之前不断地将 WebBrowser 控件添加到 XAML 标记中,并在加载所需页面后从该标记中删除它的前景不是很方便。
我的目标是访问加载的 HTML 页面上的 Click 事件调用,而不用摆弄 XAML。
是否可以访问 WebBrowser 控件的 LoadCompleted 事件而不将其绑定到 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 или не добавлен программным путем в качестве
// дочернего компонента к одному из существующих контролов окна.
}
}
实际上,在
LoadCompleted将 WPF WebBrowser 的事件添加到某个呈现的窗口或控件之前,不会触发该事件,这是一个已知问题。原因在于 WebBrowser 如何初始化其内部 Internet Explorer ActiveX 控件,该控件负责加载页面。这可以通过查看参考源中的源代码来理解。为了使
DocumentCompleted内部 ActiveX 对象的事件正常工作,ActiveXHost必须将类设置为 stateActiveXState.InPlaceActive。默认情况下,它在ActiveXState.Running(参见属性初始化)中,在调用BuildWindowCore方法时发生向 InPlaceActive 状态的转换,该方法仅在显示元素的父窗口时调用。此行为不同于 WinForms 中的类似元素,后者在初始化时立即提升为 InPlaceActive,请参见此处)。解决方案 1 - 使用 WinForms WebBrowser
WinForms 中的WebBrowser元素没有这个问题(总是引发类似的事件
DocumentCompleted),并且在功能上绝不逊色于 WPF 中的元素。您只需添加对 System.Windows.Forms 的引用并使用它。解决方案 2 - 使用屏幕外窗口
该调用
BuildWindowCore需要一个可见窗口,但没有人禁止将坐标设为负值并将窗口置于屏幕之外:解决方案 3 - 使用反射的肮脏破解
只需调用内部方法
TransitionUpTo,将常量 InPlaceActive (4) 作为参数传递: