如何在 WPF 中从它包含的 HTMLDocument 中检索 WebBrowser 控件?

How to retrieve the WebBrowser control from the HTMLDocument it contains, in WPF?

我的 WPF 应用程序正在创建多个 WebBrowser 控件。我知道如何在每个文档中操作 HtmlDocument 以及如何处理它们上的鼠标事件。 但是,在以 IHTMLEventObj2 对象作为参数的鼠标事件中,如何检索托管 WebBrowse? 我可以通过 srcElement.document 访问该文档,但是如何 'navigate up' 访问托管该文档的 WebBrowser? 我想过使用 'Tag' 属性,但 HTMLDocument 没有。 作为最后的手段,我可​​能可以使用基于 HtmlDocument 对象的散列 table,但是对于这样一个简单的事情来说这有点复杂...

Where/how 你收到鼠标事件了吗srcElement.document?好像是javascript.

如果为真,那么我很确定您无法从 JavaScript 访问 Web 控件,因为 Web 控件未在 DOM 树中公开。您可以尝试使用 window.external (或类似的)并通过它公开方法,然后让这些方法在网络浏览器上运行,但这有点令人费解,但我相信这种方式是可能的.

如果不是这样,并且如果您在 C# 中有一些鼠标事件处理程序,那么只需 link 带有网络浏览器的处理程序 事件被调用之前。而不是:

// inside your Window/etc:

private int otherData;
private void MyHandler(...args) {
    if(otherData > 5)
        browser.Navigate("foobar.html");
}

WebBrowser wb = ...;
wb.themouseevent += myhandler; // equivalent to wb.themouseevent += this.myhandler;

使用闭包或自定义对象从将 "know" 浏览器之前的对象公开处理程序:

// inside or outside your Window/etc:
class MyHandlersWithSomeData
{
    public WebBrowser browser;
    public string someContextuaData;
    public int otherData;
    ....

    public void MyHandler(...args) {
        if(otherData > 5)
            browser.Navigate("foobar.html");
    }
}

// inside your Window/etc:
WebBrowser wb = ...;
var smartHandler = new MyHandlersWithSomeData{ browser = wb, otherData = 10 };
wb.themouseevent += smartHandler.MyHandler; // note that handler is not from "this" anymore

编辑:如您所问,"simpler" 方法是使用 lambda 和闭包:

// inside your Window/etc:

private int otherData;
private void JustAMethodNotAHandler(WebBrowser browser, object sender, EventArgs args) {
    if(otherData > 5)
        browser.Navigate("foobar.html");
}

WebBrowser wb = ...;
wb.themouseevent += (sender, args) => JustAMethodNotAHandler(wb, sender, args);

然而没有魔法。在引擎盖下,它几乎与上面的示例完全相同,但有一个额外的 class,即所谓的 "closure"。此 class 将存储对 WebBrowser wb 局部变量的引用,仅由于此,当稍后调用 JustAMethodNotAHandler 时,wb 仍然可用并可传递给该方法。

但是,由于我们现在使用 lambdas((blah)=>blah 语法)来快速创建委托,因此您必须注意两件非常重要的事情:

  • JustAMethodNotAHandler 不是处理程序,它只是一个方法。 lambda 创建的匿名函数将是实际的处理程序
  • 由于匿名函数是匿名的,如果您以后想要取消注册它,您将很难过。尝试像:

    wb.themouseevent -= (sender, args) => JustAMethodNotAHandler(wb, sender, args);

将不起作用 因为每次执行该行时,都会创建一个新的处理程序,完全不等于使用 +=

创建的处理程序