为啥 WebBrowser_DocumentCompleted() 触发两次?

Posted

技术标签:

【中文标题】为啥 WebBrowser_DocumentCompleted() 触发两次?【英文标题】:Why is WebBrowser_DocumentCompleted() firing twice?为什么 WebBrowser_DocumentCompleted() 触发两次? 【发布时间】:2011-01-20 16:37:46 【问题描述】:

好吧,我正在使用一个简单的 webbrowser 控件来浏览页面,所以我需要在这样做的同时更改表单的文本。我正在使用 -

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

     this.Text += " - " + webBrowser1.Document.Domain;

但是使用断点,我注意到,这个事件触发了两次。我什至尝试过_Navigated() 事件。它也发射了两次。结果标题为"Webber - google.co.in - google.co.in" ..

我还注意到这个事件在加载 msn.com 时触发了好几次。我只是在页面完全加载完成后才尝试更改表单的文本。

有什么办法吗?

【问题讨论】:

【参考方案1】:

您可以在事件触发时检查 WebBrowser.ReadyState:

if (browser.ReadyState != WebBrowserReadyState.Complete)
    return;

整个文档准备就绪后,ReadyState 将设置为 Complete。

【讨论】:

它很可能会再次触发文件中的任何外部 javascript 链接【参考方案2】:

每次加载帧时,都会触发该事件。

另外,在你去那里之前,IsBusy 属性只会是True,而第一帧还没有加载。

void BrowserDocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

  if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
    return; 

  //The page is finished loading 

【讨论】:

我不敢问,但你把它与活动联系起来了吗?只是,文件毕竟完成了。 谢谢!正是我需要的 - 无法弄清楚为什么有些页面完全呈现,而另一些只呈现部分。【参考方案3】:

我有同样的问题,原因是,默认情况下,当您添加控件时,它会生成这样的设计器代码。

this.webBrowser1.Url =  new System.Uri("", System.UriKind.Relative);

如果您在调用后更改网址

InitializeComponent();
WebBrowser.Navigate("NewUrl.com");

它将加载两个不同的页面:About:BlankNewUrl.com

只需删除设计器代码...您将停止“双重”事件。

【讨论】:

我遇到了同样的问题,这个解决方法对我来说很好。我有点惊讶 Url 属性似乎以某种方式“入队”: DocumentCompleted 使用 e.Url == "about:blank" 触发,即使我将其挂钩 (+=) after a Url = "http://..." 声明【参考方案4】:

每帧触发一次。

【讨论】:

【参考方案5】:

如果触发两次是一个问题,那么这应该可以工作:

  string body="";

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    
        if (body == webBrowser1.Document.Body.Innerhtml) return;
        body = webBrowser1.Document.Body.InnerHtml;

        // Here is something you want
    

【讨论】:

如果正文之间的内容这么多,时间就会这么长。【参考方案6】:

当您每次订阅此事件时导航到 URL 时,您可能会多次订阅此事件,就像您使用某种方法一样。

要解决此问题,请将那条线移出方法并将其放在其他地方,每个实例只会调用一次。也许在类的构造函数中......那应该可以解决你的问题。

【讨论】:

【参考方案7】:

实际上,它并不总是被解雇。还没想明白为什么不行。我有一个计时器,只是反复检查 ReadyState 几分钟。 (使用嵌入式浏览器控件)。

【讨论】:

【参考方案8】:

推荐if (browser.ReadyState != WebBrowserReadyState.Complete)

而且当页面中有框架的时候,DocumentCompleted会被触发几次。这很难解决。有些方法比如检查url是不准确的。

顺便说一句,为什么不使用这个:

this.Text = stringA + " - " + webBrowser1.Document.Domain;

尽量使用固定前缀,问题可能会很容易解决。

【讨论】:

【参考方案9】:

How To Determine When a Page Is Done Loading in WebBrowser Control DocumentCompleted 是 WinForms 对 DocumentComplete evert 的包装,但是 WebBrowserDocumentCompletedEventArgs 隐藏了 sender 参数,因此您无法判断是哪个框架引发了事件。 或者您可以查看WebBrowser.ReadyState

【讨论】:

以上是关于为啥 WebBrowser_DocumentCompleted() 触发两次?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 DataGridView 上的 DoubleBuffered 属性默认为 false,为啥它受到保护?

为啥需要softmax函数?为啥不简单归一化?

为啥 g++ 需要 libstdc++.a?为啥不是默认值?

为啥或为啥不在 C++ 中使用 memset? [关闭]

为啥临时变量需要更改数组元素以及为啥需要在最后取消设置?

为啥 CAP 定理中的 RDBMS 分区不能容忍,为啥它可用?