引言

WebBrowser控件的DocumentCompleted事件一般就被认定为是在页面完全加载完毕后产生,而注释中也是这么写的:

但事实却并非如此。

首先它不一定会在完全加载完毕时才触发,有时就会在加载过程中就会触发。

其次按照“完全加载完毕后”来理解,会认为通常一次页面跳转只会引发一次该事件,事实也并非如此,某些页面加载时会引发十多次乃至更多。

试验

做一个简单试验,首先设计这样的界面:

然后为那个转到按钮添加单击事件处理:

private void button1_Click(object sender, EventArgs e)

{

webBrowser1.Navigate(textBox1.Text);

}

再为WebBrowser控件的DocumentCompleted事件添加处理:

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

listBox1.Items.Insert(0, webBrowser1.ReadyState);

}

在这里就是输出WebBrowser控件的ReadyState属性到列表中。

运行并测试:

可以看到加载某些页面时会引发很多次该事件,并且状态都是一连串的Interactive。

究其原因是与页面复杂度有关的,猜想是因iFrame或Ajax加载完毕而触发的。

而触发DocumentCompleted事件时ReadyState为Complete的情况通常只在每次加载页面时出现一次,所以这时我们才应认为其已完全加载。但也并非一个页面100%只会出现一次这种情况,比如页面中Google的“更多”链接点击后仅仅是弹出一个列表,但这时又会出现一次Complete。

这会导致什么问题?

假如在ReadyState为Interactive甚至是Loading时对页面实施操控,那很可能无效或引发异常。

而假如忽视这种一页多发事件的情况,会导致大量重复操作,从而引发异常或逻辑问题。

该如何解决?

以下代码可以确保你不会在未加载完毕时执行操作:

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

if (webBrowser1.ReadyState < WebBrowserReadyState.Complete) return;

//执行正常流程代码…………

}

如果需要严格控制每页只能执行一次代码,那么需要附加一个属性或变量来记录上次访问的网址,并据此进行判断:

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

if (webBrowser1.ReadyState < WebBrowserReadyState.Complete || webBrowser1.Url.ToString() == LastUrl) return;

LastUrl = webBrowser1.Url.ToString();

//执行正常流程代码…………

}

public string LastUrl

{

get

{

return _LastUrl;

}

set

{

_LastUrl = value;

}

}

private string _LastUrl;

结语

WebBrowser是非常实用的控件,但也可说是粗制滥造的典范,各种问题层出不穷,从注释对不上实际功能这一点来看,就知道开发者多么漫不经心了。还有就是ReadyState属性其实是一个非常关键的属性,而开发者却没有设置一个事件来监控其状态变更,真是太失败了。

谨慎注意WebBrowser控件的DocumentCompleted事件的更多相关文章

  1. C# WebBrowser控件使用教程与技巧收集

    常用的方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表示的网址 Navigate(strin ...

  2. C#WebBrowser控件使用教程与技巧收集--苏飞收集

    C#WebBrowser控件使用教程与技巧收集--苏飞收集 先来看看常用的方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System. ...

  3. Webbrowser控件判断网页加载完毕的简单方法 (转)

    摘自:http://blog.csdn.net/cometnet/article/details/5261192 一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,W ...

  4. C#WebBrowser控件使用教程与技巧

    获取非input控件的值 webBrowser1.Document.All["控件ID"].InnerText;或webBrowser1.Document.GetElementBy ...

  5. Webbrowser控件判断网页加载完毕的简单方法

    一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,Webbrowser控件会通过触发DocumentCompleted事件来指示网页加载完毕.但当加载的网页包含fra ...

  6. C#中的WebBrowser控件的使用

    0.常用方法   Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表示的网址 Navigate(st ...

  7. 009. C#中的WebBrowser控件的属性、方法及操作演示代码(转)

    本文转自 http://www.open-open.com/code/view/1430559996802 0.常用方法 Navigate(string urlString):浏览urlString表 ...

  8. C# WebBrowser控件详解

     作者:827969653     0.常用方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表 ...

  9. 【WPF】监听WPF的WebBrowser控件弹出新窗口的事件

    原文:[WPF]监听WPF的WebBrowser控件弹出新窗口的事件 WPF中自带一个WebBrowser控件,当我们使用它打开一个网页,例如百度,然后点击它其中的链接时,如果这个链接是会弹出一个新窗 ...

随机推荐

  1. CTSC2018&APIO2018游记

    CTSC2018&APIO2018游记 Day 0 傍晚出发,从长沙通往帝都的软卧哟. 然而长沙某中学坐高铁比我们晚出发还早到 Day 1 为了正经地写游记我决定忍住不在博客里吐槽酒店. 午饭 ...

  2. Dream_Spark-----Spark 定制版:005~贯通Spark Streaming流计算框架的运行源码

    Spark 定制版:005~贯通Spark Streaming流计算框架的运行源码   本讲内容: a. 在线动态计算分类最热门商品案例回顾与演示 b. 基于案例贯通Spark Streaming的运 ...

  3. 【干货】已Window7 系统为例,谈谈boot引导程序-------附带看看数据隐藏

    来源:Unit 3: Unix/Linux File System 3.1 Unix/Linux File System Booting Process 使用工具:EnCase Forensic 学习 ...

  4. Linux中断(interrupt)子系统之四:驱动程序接口层 & 中断通用逻辑层【转】

    转自:http://blog.csdn.net/droidphone/article/details/7497787 在本系列文章的第一篇:Linux中断(interrupt)子系统之一:中断系统基本 ...

  5. 诡异的Linux磁盘空间被占用问题,根目录满了,df和du占用不一样【转】

    新公司的测试机磁盘空间空余很小,日志很多,也很大,做个日志压缩脚本,在夜里4:30自动运行,第二天后发现磁盘空间又满了,只好删除没用的日志,清空空间,可诡异的是怎么删除没用的文件,空间还是占用很大.如 ...

  6. springcloud Eureka自我保护机制

    自我保护背景 首先对Eureka注册中心需要了解的是Eureka各个节点都是平等的,没有ZK中角色的概念, 即使N-1个节点挂掉也不会影响其他节点的正常运行. 默认情况下,如果Eureka Serve ...

  7. java 异常历史 和观点

    异常起源于PL/1和Mesa之类的系统中. 1.) 不在于编译器是否会强制程序员去处理错误,而是要由一致的,使用异常来报告错误 2.) 不在于什么时候进行检查,而是一定要有检查.

  8. centos7 mysql5.7 rpm 安装

    卸载MariaDB CentOS7默认安装MariaDB而不是MySQL,而且yum服务器上也移除了MySQL相关的软件包.因为MariaDB和MySQL可能会冲突,故先卸载MariaDB. 查看已安 ...

  9. 【记录】group_concat_max_len

    这几天在帮别人定位一个问题,结果定位了半天都没有结果.redis中取出来的数据很奇怪,每次都不一样,而且总是取不完全. 我以为是redis的内存不够,导致数据丢失,但是不应该啊,这么点数据,也不至于内 ...

  10. 004.MySQL主库手动复制至从库

    一 主库手动复制至从库 1.1 Master主库锁表 mysql> flush tables with read lock; Query OK, 0 rows affected (0.00 se ...