zoukankan      html  css  js  c++  java
  • 谨慎注意WebBrowser控件的DocumentCompleted事件

    image

    引言

    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

  • 相关阅读:
    Java对象转型
    .Net之路(十二)Cookie对象
    java学习笔记-包
    MongoDB的安装和简单使用
    考试系统维护中对项目管理的一点体会
    .Net之路(十一)StringBuilder和string
    考试系统调试优化总结
    我的2013——走过就有收获
    针对:Arraylist集合无法修改,下一次枚举无法操作的解决方案
    函数第二部分:为什么说动态参数是没有计划好的参数-Python基础前传(11)
  • 原文地址:https://www.cnblogs.com/SkyD/p/1540028.html
Copyright © 2011-2022 走看看