WPF 客户端浏览器 添加Loading加载进度

摘要:
加载进度显示界面显示1.界面显示,加载进度样式可参考:绕圈进度条2.添加Loading状态枚举。进度显示处理在封装相应浏览器后,针对三个事件DocumentCompleted、ProgressChanged、NavigateError作进度显示的处理。此事件只有Navigate调用后,才会触发ProgressChanged进度变更通知,Navigate、Refresh调用后都会触发。当前进度大于0时,立即结束Loading,减少延时。经调试发现ProgressedChanged的事件参数中,MaximumProgress一直等于0。

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

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

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

加载进度显示

界面显示

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

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

1     public enumLoadingState
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(objectsender, 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(objectsender, 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(objectsender, 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(objectsender, 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 boolcancel)
2 {
3         _browser?.NavigateError?.Invoke(this, new BrowserExtendedNavigateErrorEventArgs((string)url, (string)frame, (int)statusCode, cancel));
4     }

Cef浏览器

1     private voidRegister()
2 {
3         _cefBrowser.LoadingStateChanged +=CefBrowserOnLoadingStateChanged;
4         _cefBrowser.LoadError +=CefBrowserOnLoadError;
5 }
6     private void CefBrowserOnLoadError(objectsender, 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(objectsender, 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

免责声明:文章转载自《WPF 客户端浏览器 添加Loading加载进度》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇HTML与CSS布局技巧AUC指标深度理解下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

npm 安装包失败 --- 清除npm缓存

在网上找清缓存的办法,第一个就是 npm cache verify, 没有效果,还有一个方法npm cache clean --force, 还是没有作用,最后想到到底缓存放到什么地方,因为以前全局安装某个命令的时候,有一个AppData/roaming 的文件夹,里面放到就是npm 的命令, 这时搜了一下npm cache 存放的位置,也是在这个地方,C...

c# wpf 条状刻度线,仪表盘的做法

网上看到 https://www.cnblogs.com/congqiandehoulai/p/12733245.html  照着例子做,一直不行,最后发现了问题。 1 需要添加两个引用 Microsoft.Expression.ControlsMicrosoft.Expression.Drawing 这两个dll需要引用到项目里,可以在自己的电脑里查到...

Linux上运行安卓应用:安装使用Anbox

文章目录 #0x0 简介 #0x1 安装教程 #0x11 第一步,安装需要的内核模块 #0x12 安装Anbox #0x2 使用Anbox #0x21 一些简单的设置 #0x22 安装APK #0x3 卸载Anbox #0x0 简介 使用Linux运行安卓软件,类似于虚拟机,这种软件有不少 比如Genymotion,Andy OS,An...

常用移动web开发框架--转载

  阅读目录 1.1 jQuery mobile flat-ui 主题 1.2jQuery mobile Bootstrap 主题 4.1 GMU   4.2 Clouda+  4.3 efe    5.1 Spirit 5.2 Frozen UI       纯粹的总结一下移动web开发框架,移动web开发框架有jQuery Mobile 、...

上传大文件的解决方案

需求: 项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在20G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以20G来进行限制。 PC端全平台支持,要求支持Windows,Mac,Linux 支持所有浏览器。 支持文件批量上传 支持文件夹上传,且要求在服务端保留层级结构。文件夹数量要求支持到10W。 支持大文件断点续传,要求...

wpf prism加载独立模块实例

一、首先看看文件的组织架构 module1 module2生成dll某块。Shell来显示管理模块 二,看看关键bootstrapper类 using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tas...