WebBrowser的DocumentCompleted事件会被触发多次

8
我一直在研究这个问题,所有人都认为解决方法是检查Web浏览器的ReadyState直到设置为Complete。但实际上,有时候事件会被触发多次,且ReadyState设置为Complete。
我认为那个.NET WebBrowser很差,可能通过使用底层DOM组件来找到一个解决方案。唯一的问题是,我不知道如何访问WebBrowser后面的DOM组件来触发DocumentCompleted事件。
4个回答

32

DocumentCompleted事件将为网页中的每个框架(frame)触发。一种更复杂的方法是逐帧计数,向您展示如何访问DOM:

private int mFrameCount;

private void startNavigate(string url) {
  mFrameCount = 0;
  webBrowser1.Navigate(url);
}

private void DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
  mFrameCount += 1;
  bool done = true;
  if (webBrowser1.Document != null) {
    HtmlWindow win = webBrowser1.Document.Window;
    if (win.Frames.Count > mFrameCount && win.Frames.Count > 0) done = false;
  }
  if (done) {
    Console.WriteLine("Now it is really done");
  }
}

简单的方法是检查完成加载的URL:

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    if (e.Url.Equals(webBrowser1.Url)) {
        Console.WriteLine("Now it is really done");
    }
}

这个答案的简单方法对我很有帮助。尽管我正在使用axWebBrowser1控件,但最终我使用了以下代码:if (e.uRL.Equals(axWebBrowser1.LocationURL)) - IamBatman
我使用一个静态帮助类:public static class WebBrowserHelper { public static bool DocumentIsReallyCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { WebBrowser browser = (WebBrowser)sender; return e.Url.Equals(browser.Url); } } - Jack Griffin

0

如果页面使用Javascript或<meta refresh>重定向到另一个页面,那么可能会发生这种情况。

如果是这样的话,没有好的解决方法。


0

我找不到任何可以百分之百确定的东西。

提到的示例(e.Url.Equals(webBrowser1.Url))可能适用于简单的WebBrowser.Navigate(url),但在我的情况下,我通过代码单击节点以打开现有帧中的新帧。大多数时候,“Navigating”和“DocumentCompleted”触发的次数将是相同的,但并非总是如此。 “isBusy = false”和“ReadyState = Complete”将始终在完成时出现(至少目前是这样),但它还会多次处于加载状态时出现这种状态。对于我来说,计算框架数量似乎也没有用,例如,在一个案例中,DocumentCompleted被触发了23次,但所有框架和子(子-子-子等)框架总共是14个。

唯一看起来有效的事情就是等待短时间(1或2秒?)以查看是否发生任何事情(任何事件被触发,任何状态更改)。

嗯,我为自己找到了另一种解决方案。我们经常不关心整个页面是否已加载,我们经常希望某些元素存在。因此,在每个DocumentCompleted之后,并且当“isBusy = false”和“ReadyState = Complete”时,我们可以搜索DOM以查找该元素是否存在。


0
在我的经验中,除非DocumentCompleted事件已经触发了一段时间,否则无法确定网页何时加载完成。因此,每次DocumentCompleted事件触发时,我会刷新一个大约1000毫秒的计时器。然后当计时器超时时,我处理网页。

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