zoukankan      html  css  js  c++  java
  • WPF 客户端浏览器 添加Loading加载进度

    在windows开发界面时,使用浏览器来请求和显示网页内容,是比较常见的。

    但是在请求网页内容时,因网速或者前端功能复杂加载较慢,亦或者加载时遇到各种问题,如空白/黑屏/加载不完整/证书问题等。

    因此需要一个加载进度/加载失败的显示界面。

     加载进度显示

    界面显示

    1. 界面显示,加载进度样式可参考: 绕圈进度条

    2. 添加Loading状态枚举。不加载/加载中/加载失败

    1     public enum LoadingState
    2     {
    3         NotLoading,//正常的网页内容界面
    4         Loading,   //加载进度显示
    5         Error,     //加载失败界面
    6     }

    在控件内添加LoadingState附加属性,前端界面通过绑定此附加属性来确定是否显示,LoadingState的变更时,界面显示则直接变更。

    进度显示处理

    在封装相应浏览器后,针对三个事件DocumentCompleted、ProgressChanged、NavigateError作进度显示的处理。

    结束加载进度

    1. DocumentCompleted文档加载完成后,结束加载进度。此事件只有Navigate调用后,才会触发
    2. ProgressChanged进度变更通知,Navigate、Refresh调用后都会触发。因为Navigate调用后,同一进度会重复触发ProgressChanged,ProgressChanged在Navigate调用时触发并没有任何意义,因此在DocumentCompleted之后再添加事件的订阅,ProgressChanged只开放给Refresh方法。
    3. 当前进度大于0时,立即结束Loading,减少延时。
     1     /// <summary>
     2     /// 文档加载完成
     3     /// </summary>
     4     /// <remark>Navigate方法触发,Refresh方法不会触发</remark>
     5     /// <remark>在首次加载时,添加DocumentCompleted订阅</remark>
     6     /// <param name="sender"></param>
     7     /// <param name="e"></param>
     8     private void Browser_OnDocumentCompleted(object sender, HtmlDocumentCompletedEventArgs e)
     9     {
    10         //当前Loading状态不是Error的情况下,才结束加载
    11         if (LoadingState == LoadingState.Loading)
    12         {
    13             LoadingState = LoadingState.NotLoading;
    14         }
    15 
    16         //显示网页内容首次加载后,再订阅加载进度事件
    17         _browser.ProgressChanged -= Browser_ProgressChanged;
    18         _browser.ProgressChanged += Browser_ProgressChanged;
    19         OnDocumentCompleted(e);
    20     }
    21 
    22     /// <summary>
    23     /// 加载进度事件
    24     /// </summary>
    25     /// <remark>Navigate会触发多次ProgressChanged事件,所以此事件订阅不应开放给Navigate</remark>
    26     /// <remark>Refresh调用后,会触发一次</remark>
    27     /// <param name="sender"></param>
    28     /// <param name="e"></param>
    29     private void Browser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
    30     {
    31         //当前进度大于0,且当前Loading状态是Loading的情况下,才结束Loading动画
    32         if (e.CurrentProgress > 0 && LoadingState == LoadingState.Loading)
    33         {
    34             LoadingState = LoadingState.NotLoading;
    35         }
    36     }

    值得注意的是,如果按照如上设置,当IE8环境升级到IE11后,因WebBrowserProgressChangedEventArgs事件参数返回异常,不会结束Loading。

    问题跟进记录:When IE updates from version 8 to version 11,this eventArgs value for event ProgressChanged is weird. 

    原因:调用refresh方法。经调试发现ProgressedChanged的事件参数中,MaximumProgress一直等于0。
    但是,正常情况下,同样的电脑环境,win7 IE8或者IE11下,refresh方法,返回的MaximumProgress不为0。

    推荐分析:升级后,原有IE版本的注册项遗留,导致冲突。

    解决方案:添加e.CurrentProgress == e.MaximumProgress的条件判断。

     1     private void Browser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
     2     {
     3         //当以下俩种条件符合时,才结束Loading动画
     4         //1.当前Loading状态是Loading的情况下
     5         //2.当前进度大于0,或者当前进度等于进度上限阀值
     6         if (LoadingState == LoadingState.Loading && (e.CurrentProgress > 0 || e.CurrentProgress == e.MaximumProgress))
     7         {
     8             LoadingState = LoadingState.NotLoading;
     9         }
    10     }

    PS:微软小组成员推荐使用WebView,然而这个只为Win10的Microsoft Edge开发的控件,只能在win10上运行且只支持.NET4.6.2及以上,限制多多。

    加载出错

     1     private void Browser_NavigateError(object sender, BrowserExtendedNavigateErrorEventArgs e)
     2     {
     3         e.Cancel = true;
     4         LoadingState = LoadingState.Error;
     5 
     6         //当前不是网络问题的异常,记录异常日志
     7         if (e.StatusCode != NavigationErrorHttpStatusCode.INET_E_RESOURCE_NOT_FOUND)
     8         {
     9             Console.WriteLine($"WebBrowser无法连接服务器:{e.Url},异常信息为:{e.StatusCode},异常Code为:{ (int)e.StatusCode }");
    10         }
    11     }

    浏览器事件处理

    针对如上三个事件,DocumentCompleted、ProgressChanged、NavigateError

    winform版IE浏览器

    1     /// <summary>
    2     ///<see cref="T:System.Windows.Forms.WebBrowser" /> 控件完成加载文档时发生。
    3     /// </summary>
    4     [SRCategory("CatBehavior")]
    5     [SRDescription("WebBrowserDocumentCompletedDescr")]
    6     public event WebBrowserDocumentCompletedEventHandler DocumentCompleted;
    1     /// <summary>
    2     ///<see cref="T:System.Windows.Forms.WebBrowser" /> 控件已更新有关要导航到的文档的下载进度的信息时发生。
    3     /// </summary>
    4     [SRCategory("CatAction")]
    5     [SRDescription("WebBrowserProgressChangedDescr")]
    6     public event WebBrowserProgressChangedEventHandler ProgressChanged;

    NavigateError加载失败事件,需要重写CreateSink、DetachSink。在对应的cookie中添加额外事件的处理:(在此不详述)

    1     public void NavigateError(object pDisp, ref object url, ref object frame, ref object statusCode, ref bool cancel)
    2     {
    3         _browser?.NavigateError?.Invoke(this, new BrowserExtendedNavigateErrorEventArgs((string)url, (string)frame, (int)statusCode, cancel));
    4     }

    Cef浏览器

     1     private void Register()
     2     {
     3         _cefBrowser.LoadingStateChanged += CefBrowserOnLoadingStateChanged;
     4         _cefBrowser.LoadError += CefBrowserOnLoadError;
     5     }
     6     private void CefBrowserOnLoadError(object sender, LoadErrorEventArgs args)
     7     {
     8         // Don't display an error for downloaded files where the user aborted the download.
     9         if (args.ErrorCode == CefErrorCode.Aborted)
    10         {
    11             return;
    12         }
    13         _isLoadError = true;
    14         DispatcherUtil.Invoke(() =>
    15         {
    16             NavigateError?.Invoke(this, new BrowserExtendedNavigateErrorEventArgs(args.FailedUrl, args.Frame.Name, (int)args.ErrorCode, false));
    17         });
    18     }
    19 
    20     private void CefBrowserOnLoadingStateChanged(object sender, LoadingStateChangedEventArgs args)
    21     {
    22         //isLoading为false,代表LoadingCompleted
    23         //_isLoadError为false,代表未加载出错
    24         if (!args.IsLoading && !_isLoadError)
    25         {
    26             DispatcherUtil.Invoke(() =>
    27             {
    28                 DocumentCompleted?.Invoke(this, new HtmlDocumentCompletedEventArgs(null));
    29             });
    30         }
    31     }

    关键字:客户端浏览器进度Loading、IE浏览器loading、Cef浏览器loading

  • 相关阅读:
    把VB.NET代码转换为C#代码的方法
    离散数学 第二章 谓词逻辑 26 前束范式
    离散数学 第二章 谓词逻辑 27 谓词演算的推理理论
    asp.net中怎样用Javascript控制RequiredFieldValidator控件什么时候启用,什么时候不启用验证?
    离散数学中的IFF标记
    BIRT Overview
    离散数学 第二章 谓词逻辑 25 谓词演算的等价式和蕴涵式
    getRemoteAddr()和getRemoteHost()的区别
    scp 不用密码
    利用spring实现javamail功能
  • 原文地址:https://www.cnblogs.com/kybs0/p/9698736.html
Copyright © 2011-2022 走看看