WebBrowser控件的OnPropertyChange事件没有触发

3
我有一个网页,上面有一个输入按钮。点击这个按钮后,一些数据会在特定的div中加载。我的问题是我无法捕获这些数据。
以下代码是我解决这个问题的尝试,但没有成功。
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    HtmlElement div_result = webBrowser1.Document.GetElementById("div_result");
    div_result.AttachEventHandler("onpropertychange", new EventHandler(resultEventHandler));
}
private void resultEventHandler(object sender, EventArgs e)
{
    MessageBox.Show("Loaded");
}

如果我点击输入按钮,div的内容会被修改,但是resultEventHandler不会触发。

所以,我的两个问题是:

  1. 在这段代码中,我的错误在哪里?
  2. 有没有一种“正常的方法”(我指的是不使用计时器或Aplication.DoEvents())在C#中使用WebBrowser控件来处理ajax?

是因为“更改子元素的innerText或innerHTML不会导致父元素的onpropertychange事件触发。”吗?因为当内容更改时,DIV的任何属性都不需要更改。 http://msdn.microsoft.com/en-us/library/ie/ms536956(v=vs.85).aspx - aliassce
3个回答

0

我无法确定为什么HtmlElement事件对你不起作用。但是我曾遇到过同样的问题,并通过使用COM包装器解决了它:

mshtml.HTMLDocumentClass doc = (mshtml.HTMLDocumentClass)webBrowser1.Document.DomDocument;
mshtml.IHTMLElement2 div_result = (mshtml.IHTMLElement2)doc.getElementById("div_result");
mshtml.HTMLElementEvents2_Event events = (mshtml.HTMLElementEvents2_Event)div_result;
events.onpropertychange += resultEventHandler;

0
更改子元素的innerText或innerHTML不会导致父元素触发onpropertychange事件。

我从 MSDN 上阅读了这个笔记,但是我没有子元素。我有一个非常简单的网页,专门为这个实验制作:http://fast-index.ru/wbajax.php。 - zerocube

0

这可能有点晚了,但如果您仍然想知道,这里是:

1 - HtmlElement div_result = webBrowser1.Document.GetElementById("div_result"); 第一行代码在网页加载完成并且浏览器调用DocumentCompleted事件时执行。在事件处理程序中,您首先检索指向DOM元素“div_result”的指针,并将其分配给名为div_result的HtmlElement类型变量。

2 - div_result.AttachEventHandler("onpropertychange", new EventHandler(resultEventHandler)); 第二行代码注册“onpropertychange”事件,并将方法resultEventHandler分配为侦听器方法。

每次单击Web页面上的按钮时,该按钮(我假设)位于一个表单中,该表单被提交以导致网页加载;顺便说一下,您没有指定单击按钮时使用的哪种POST方法(GET还是POST)。当网页下载完成并且DOM元素树构建完成时,将调用您的DocumentCompleted事件。您的DocumentCompleted事件处理程序方法执行了上述说明的指令。

每次单击按钮时,您的网页都会重新加载,并重新分配onpropertychange事件的事件侦听器。您只分配了事件侦听器。事件将永远不会被调用。每次单击按钮时,它只是被定义。您有一个经典的先有鸡还是先有蛋的问题。但在您的情况下,您的鸡是按钮单击事件导致DocumentCompleted方法运行,该方法重置方法中所有变量的状态,而您的蛋是希望在单击网页上的按钮之前获取指向DIV元素的onpropertychange事件的指针。如何在构建DOM之前为htmlelement分配事件侦听器?在包含DocumentCompleted方法的类中放置一个布尔标志变量并设置其初始状态。将div_result变量移出DocumentCompleted方法以增加其范围并保存其状态跨越按钮单击事件。这样,您将获得指向div元素的指针,并在第一次下载网页时设置其onpropertychange事件侦听器。如果您只想设置一次指向DIV元素的onpropertychange事件侦听器,则添加一个测试(我在下面的示例代码中放置了一个测试),下次单击按钮时,您的事件将触发。注意!确保在存储任何网页元素或其事件的指针后不要添加或删除任何元素到您的网页。否则,您将不得不重新解析DOM以获取指向元素在DOM树中的新位置的指针。

//请见下文:

class SomeClass
{
    bool DocumentHasLoaded = false;
    HtmlElement div_result = null;

    //Constructor and other methods go here....

    //Then change your DocumentCompleted method to look like this:
    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {

        if (DocumentHasLoaded == false)  // I prefer using a ! before the variable instead
        {
            DocumentHasLoaded = true;    // You will have to create your own appropriately timed mechanism to reset this variable's state should you want to execute the whole process again.
            div_result = webBrowser1.Document.GetElementById("div_result");
            div_result.AttachEventHandler("onpropertychange", new EventHandler(resultEventHandler));
        }
    }
}

为了回答你的第二个问题,我需要更多关于DIV中加载的数据的信息;例如它来自哪里,是什么类型的,以及你能想到的任何其他相关信息。

我更喜欢在变量前使用!,那么为什么要做其他的呢?这就是你的答案。 - weston
如果按钮单击导致页面刷新,则此分析是有意义的。但是,如果按钮单击会触发页面中的某些(客户端)JavaScript,其中该JS会更改“div_result”元素,则C# onpropertychange事件处理程序应该被触发,不是吗? 顺便说一句,我有一个类似的情况,C#事件处理程序过去曾被调用,但现在未被调用。我目前怀疑是由于Windows更新导致MSIE行为发生了变化。请参见 also - shaun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接