谨慎注意WebBrowser控件的DocumentCompleted事件
引言
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事件的更多相关文章
- C# WebBrowser控件使用教程与技巧收集
常用的方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表示的网址 Navigate(strin ...
- C#WebBrowser控件使用教程与技巧收集--苏飞收集
C#WebBrowser控件使用教程与技巧收集--苏飞收集 先来看看常用的方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System. ...
- Webbrowser控件判断网页加载完毕的简单方法 (转)
摘自:http://blog.csdn.net/cometnet/article/details/5261192 一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,W ...
- C#WebBrowser控件使用教程与技巧
获取非input控件的值 webBrowser1.Document.All["控件ID"].InnerText;或webBrowser1.Document.GetElementBy ...
- Webbrowser控件判断网页加载完毕的简单方法
一般情况下,当ReadyState属性变成READYSTATE_COMPLETE时,Webbrowser控件会通过触发DocumentCompleted事件来指示网页加载完毕.但当加载的网页包含fra ...
- C#中的WebBrowser控件的使用
0.常用方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表示的网址 Navigate(st ...
- 009. C#中的WebBrowser控件的属性、方法及操作演示代码(转)
本文转自 http://www.open-open.com/code/view/1430559996802 0.常用方法 Navigate(string urlString):浏览urlString表 ...
- C# WebBrowser控件详解
作者:827969653 0.常用方法 Navigate(string urlString):浏览urlString表示的网址 Navigate(System.Uri url):浏览url表 ...
- 【WPF】监听WPF的WebBrowser控件弹出新窗口的事件
原文:[WPF]监听WPF的WebBrowser控件弹出新窗口的事件 WPF中自带一个WebBrowser控件,当我们使用它打开一个网页,例如百度,然后点击它其中的链接时,如果这个链接是会弹出一个新窗 ...
随机推荐
- Ubuntu14.04搭建Android O编译环境
一.搭建环境 官方参考文档: 1.代号.标签和版本号 2.Factory Images 3.Driver Binaries 4.工具链 软硬件版本: 1.系统平台:I5-8500T+8G+1T,Ub ...
- ipython的%matplotlib inline如何改写在Python
ipython notebook中有一个相当方便的语句: %matplotlib inline,可以实现运行cell即出现结果图像.但是如果想写在Python程序内,貌似直接%matplotlib i ...
- H5开发APP考题和答案
{ "last_updated": { "$date": 1544276670569 }, "page_count": 1, "a ...
- Ubuntu 12.04 安装Tomcat7
1.下载Tomcat7 打开Tomcat官网 http://tomcat.apache.org,在左边的导航栏的“Download"中找到Tomcat7.0目录,点击后进入Tomcat7的页 ...
- java 多重继承
接口不仅仅只是一种更纯粹形式的抽象类,它的目标比这更高,因为接口是根本没有任何具体实现的--也就是说,没有任何与接口相关的存储,因此也就无法阻止多个接口的组合, 在导出类中,不强制要求必须有一个抽象的 ...
- python中使用pillow绘制汉字
# pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pillow from PIL import Image, ImageFont, I ...
- 如何区分prometheus中Histogram和Summary类型的metrics?
要理解它们的区别,关键还是告业务应用. 但如何在学习时,如何区分呢? 有以下几个维度: histogram有bucket,summary在quatile. summary分位数是客户端计算上报,his ...
- day13--开发堡垒机
本节内容 项目实战:运维堡垒机开发 商业:<齐治--堡垒机> 前景介绍 https://www.cnblogs.com/alex3714/articles/ ...
- select 详解
In summary, a socket will be identified in a particular set when select returns if: readfds:If liste ...
- 017.Zabbix宏介绍
一 宏介绍 Zabbix宏的作用是便于在模板.Items.Trigger中的引用,名称为{$名称},宏的字符范围为:A~Z/0~9/_. 如:net.tcp.service[ssh,{$SSH_POR ...