谨慎注意WebBrowser控件的DocumentCompleted事件

简介:

引言

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

image

但事实却并非如此。

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

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

试验

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

image

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

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属性到列表中。

运行并测试:

image

 

 

可以看到加载某些页面时会引发很多次该事件,并且状态都是一连串的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控件使用技巧分享 在WebBrowser中通过模拟键盘鼠标操控网页中的文件上传控件

 

下载本文的示例源代码:http://www.uushare.com/user/icesee/file/1869325

下载本文的XPS版本:http://www.uushare.com/user/icesee/file/1869320


本文转自斯克迪亚博客园博客,原文链接:http://www.cnblogs.com/SkyD/archive/2009/08/06/1540028.html,如需转载请自行联系原作者

相关文章
|
4月前
|
C#
C# 禁止ComboBox滚动事件细谈
C# 禁止ComboBox滚动事件细谈
|
JavaScript C#
C#(WPF)去除事件中注册的事件处理方法!
在WPF中,移除一个事件中已经注册的处理方法,看似简单,实际还是很痛苦的一件事情。因为C#的灵活性,定义事件的方法也是多种多样。我自己定义了一个事件: public event EventHandler TestEvent; 当我想注销这个事件上注册的所有方法的时候,我可以按如下的方法进行 Delegate[] dels = TestEvent.
3993 0
|
Web App开发 前端开发 C#
WebBrowser与IE的关系,如何设置WebBrowser工作在IE9模式下?
一.问题的提出 偶然发现,Winform里的WebBrowser和IE实际安装的版本似乎并不同步,很有趣!   下面有张图,里面一个窗口是用IE9打开某网站,另一个窗口是用Winform+WebBrowser打开同样的网站,有意思的事情出现了。
1275 0
|
C#
WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件
原文:WPF,强制捕获鼠标事件,鼠标移出控件外依然可以执行强制捕获的鼠标事件 在WPF中,只有鼠标位置在某个控件上的时候才会触发该控件的鼠标事件。例如,有两个控件都注册了MouseDown和MouseUp事件,在控件1上按下鼠标,不要放开,移动到控件2上再放开。
2303 0