.NET混合开发解决方案9 WebView2控件的导航事件
WebView2控件应用详解系列博客
.NET混合开发解决方案2 WebView2与Edge浏览器的区别
.NET混合开发解决方案5 WebView2运行时与分发应用
.NET混合开发解决方案7 WinForm程序中通过NuGet管理器引用集成WebView2控件
.NET混合开发解决方案8 WinForm程序中通过设置固定版本运行时的BrowserExecutableFolder属性集成WebView2控件
在我的博客《.NET混合开发解决方案7 WinForm程序中集成WebView2》中介绍了WinForm程序中集成WebView2组件的详细步骤以及注意事项。这只是最基本的应用,WebView2功能之所以强大,是因为它提供了很多开放的属性与事件供开发者调用以完成复杂的功能。具体可以参考我的博客《.NET混合开发解决方案2 WebView2与Edge浏览器的区别》。
本文介绍WebView2应用程序的导航事件。当WebView2实例中显示的内容发生特定的异步操作时,导航事件会运行。例如,当WebView2用户导航到新网站时,本机内容(WinForm、WPF、Win32、WinUI)通过侦听 NavigationStarting 事件来侦听更改。导航操作完成后,NavigationCompleted 事件将运行。
导航事件的正常顺序为:
- NavigationStarting
- SourceChanged
- ContentLoading
- HistoryChanged
- BasicAuthenticationRequested
- DOMContentLoaded
- NavigationCompleted
以下事件描述每次导航操作期间 WebView2 的状态:
上图显示了在各自的事件参数上具有相同NavigationId属性的导航事件。
- 使用导航ID(在NavigationId事件中提供)跟踪每个新文档的导航事件。每次成功导航到新文档时,WebView2的NavigationId事件都会发生更改。
- 具有不同NavigationId事件实例的导航事件可能会重叠。例如,启动导航事件时,必须等待相关的NavigationStarting事件。如果随后启动另一个导航,您将看到以下序列:
- 第一次导航的 NavigationStarting 事件。
- 第二次导航的 NavigationStarting 事件。
- 第一次导航的 NavigationCompleted 事件。
- 第二次导航的所有其他相应导航事件。
- 在错误情况下,可能有或可能没有内容加载事件,这取决于导航是否继续导航到错误页面。
- 如果发生HTTP重定向,则一行中有多个NavigationStarting事件,其中后面的事件参数设置了IsRedirect属性;但是,NavigationId事件保持不变。
- 相同的文档导航事件(例如导航到同一文档中的片段)不会导致NavigationStarting事件,也不会增加NavigationId事件。
- 要监视或取消WebView2实例中子框架内的导航事件,请使用FrameNavigationStarting和FrameNavigationCompleted事件。这些事件的行为类似于等效的非框架对应事件。
当在文本框中输入目标网址后,点击【导航】按钮,具体执行逻辑如下
发生错误时,会引发以下事件,这可能取决于对错误网页的导航:
SourceChanged
ContentLoading
HistoryChanged
如果发生HTTP重定向,则一行中有多个NavigationStarting事件。
先看一个效果动画
逻辑代码
1 public partial class Frm2Navigation : Form 2 { 3 public Frm2Navigation() 4 { 5 InitializeComponent(); 6 7 InitializeAsync(); 8 9 webView2.CoreWebView2InitializationCompleted += WebView2_CoreWebView2InitializationCompleted; 10 11 webView2.NavigationStarting += WebView2_NavigationStarting; 12 webView2.NavigationCompleted += WebView2_NavigationCompleted; 13 } 14 15 async void InitializeAsync() 16 { 17 await webView2.EnsureCoreWebView2Async(null); 18 } 19 20 private void WebView2_CoreWebView2InitializationCompleted(object? sender, CoreWebView2InitializationCompletedEventArgs e) 21 { 22 if (e.IsSuccess == false) 23 { 24 MessageBox.Show("WebView2_CoreWebView2InitializationCompleted 事件,发生异常。" 25 + Environment.NewLine + e.InitializationException.Message, 26 "提示", MessageBoxButtons.OK, MessageBoxIcon.Error); 27 } 28 29 webView2.SourceChanged += WebView2_SourceChanged; 30 webView2.ContentLoading += WebView2_ContentLoading; 31 webView2.CoreWebView2.HistoryChanged += CoreWebView2_HistoryChanged; 32 webView2.CoreWebView2.DOMContentLoaded += CoreWebView2_DOMContentLoaded; 33 34 webView2.CoreWebView2.BasicAuthenticationRequested += CoreWebView2_BasicAuthenticationRequested; 35 webView2.CoreWebView2.ProcessFailed += CoreWebView2_ProcessFailed; 36 } 37 38 private void WebView2_NavigationStarting(object? sender, CoreWebView2NavigationStartingEventArgs e) 39 { 40 string uri = e.Uri; 41 if (!uri.StartsWith("https://")) 42 { 43 //webView2.CoreWebView2.ExecuteScriptAsync($"alert('{uri} 不安全, 请尝试https链接。')"); 44 45 DialogResult dr = MessageBox.Show($"{uri} 不安全, 请尝试https链接。\r\n\r\n 确定要访问吗?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); 46 if (dr == DialogResult.Cancel) 47 { 48 e.Cancel = true; 49 } 50 } 51 } 52 53 private void WebView2_SourceChanged(object? sender, CoreWebView2SourceChangedEventArgs e) 54 { 55 //if(e.IsNewDocument) 56 //{ 57 // webView2.CoreWebView2.ExecuteScriptAsync("alert('WebView2_SourceChanged事件。= e.IsNewDocument = true')"); 58 //} 59 60 MessageBox.Show("WebView2_SourceChanged 事件。" 61 + Environment.NewLine + "e.IsNewDocument = " + e.IsNewDocument, 62 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 63 } 64 65 private void WebView2_ContentLoading(object? sender, CoreWebView2ContentLoadingEventArgs e) 66 { 67 //webView2.CoreWebView2.ExecuteScriptAsync("alert('WebView2_SourceChanged事件。= e.IsNewDocument = true')"); 68 69 MessageBox.Show("WebView2_ContentLoading 事件。" 70 + Environment.NewLine + "e.IsErrorPage = " + e.IsErrorPage, 71 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 72 } 73 74 private void CoreWebView2_HistoryChanged(object? sender, object e) 75 { 76 MessageBox.Show("CoreWebView2_HistoryChanged 事件。", 77 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 78 } 79 80 private void CoreWebView2_DOMContentLoaded(object? sender, CoreWebView2DOMContentLoadedEventArgs e) 81 { 82 MessageBox.Show("CoreWebView2_DOMContentLoaded 事件。" 83 + Environment.NewLine + "e.NavigationId = " + e.NavigationId, 84 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 85 } 86 87 private void WebView2_NavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e) 88 { 89 MessageBox.Show("WebView2_NavigationCompleted 事件。" 90 + Environment.NewLine + "e.NavigationId = " + e.NavigationId 91 + Environment.NewLine + "e.IsSuccess = " + e.IsSuccess 92 + Environment.NewLine + "e.WebErrorStatus = " + e.WebErrorStatus, 93 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 94 } 95 96 97 private void CoreWebView2_ProcessFailed(object? sender, CoreWebView2ProcessFailedEventArgs e) 98 { 99 MessageBox.Show("CoreWebView2_ProcessFailed 事件。" 100 + Environment.NewLine + "e.ExitCode = " + e.ExitCode 101 + Environment.NewLine + "e.FrameInfosForFailedProcess = " + e.FrameInfosForFailedProcess 102 + Environment.NewLine + "e.ProcessDescription = " + e.ProcessDescription 103 + Environment.NewLine + "e.ProcessFailedKind = " + e.ProcessFailedKind 104 + Environment.NewLine + "e.Reason = " + e.Reason, 105 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 106 } 107 108 109 private void CoreWebView2_BasicAuthenticationRequested(object? sender, CoreWebView2BasicAuthenticationRequestedEventArgs e) 110 { 111 MessageBox.Show("CoreWebView2_BasicAuthenticationRequested 事件。" 112 + Environment.NewLine + "e.Uri = " + e.Uri 113 + Environment.NewLine + "e.Cancel = " + e.Cancel 114 + Environment.NewLine + "e.Challenge = " + e.Challenge 115 + Environment.NewLine + "e.Response = " + e.Response, 116 "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); 117 118 } 119 120 121 // 访问url 122 private void btnGo_Click(object sender, EventArgs e) 123 { 124 string rawUrl = txtUrl.Text; 125 if (string.IsNullOrWhiteSpace(rawUrl)) 126 { 127 MessageBox.Show("请输入网址。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); 128 129 txtUrl.Focus(); 130 131 return; 132 } 133 134 Uri uri; 135 136 if (Uri.IsWellFormedUriString(rawUrl, UriKind.Absolute)) 137 { 138 uri = new Uri(rawUrl); 139 } 140 else if (rawUrl.Contains(" ") == false && rawUrl.Contains(".") == false) 141 { 142 // 无效的URI包含一个点且没有空格,请尝试在前面添加http://标记 143 uri = new Uri("http://" + rawUrl); 144 } 145 else if (rawUrl.StartsWith("http://") == false) 146 { 147 uri = new Uri("http://" + rawUrl); 148 } 149 else 150 { 151 // 其他情况将其视为网络搜索 152 uri = new Uri("https://bing.com/search?q=" + string.Join("+", Uri.EscapeDataString(rawUrl).Split(new string[] { "%20" }, StringSplitOptions.RemoveEmptyEntries))); 153 } 154 155 //webView2.CoreWebView2.Navigate(url.Trim()); 156 webView2.Source = uri; 157 } 158 }
注意事项
CoreWebview2的相关事件必须在它的 CoreWebView2InitializationCompleted 事件(CoreWebView2对象初始化完成后事件)里面注册
- webView2.CoreWebView2.HistoryChanged
- webView2.CoreWebView2.DOMContentLoaded
- webView2.CoreWebView2.BasicAuthenticationRequested
- webView2.CoreWebView2.ProcessFailed
如上第31、32、34、35行。
成在管理,败在经验;嬴在选择,输在不学! 贵在坚持!
个人作品
BIMFace.SDK.NET
开源地址:https://gitee.com/NAlps/BIMFace.SDK
系列博客:https://www.cnblogs.com/SavionZhang/p/11424431.html
系列视频:https://www.cnblogs.com/SavionZhang/p/14258393.html
技术栈
1、Visual Studio、.NET Core/.NET、MVC、Web API、RESTful API、gRPC、SignalR、Java、Python
2、jQuery、Vue.js、Bootstrap、ElementUI
3、数据库:分库分表、读写分离、SQLServer、MySQL、PostgreSQL、Redis、MongoDB、ElasticSearch、达梦DM
4、架构:DDD、ABP、SpringBoot、jFinal
5、环境:跨平台、Windows、Linux、Nginx
6、移动App:Android、IOS、HarmonyOS、微信小程序、钉钉、uni-app、MAUI
分布式、高并发、云原生、微服务、Docker、CI/CD、DevOps、K8S;Dapr、RabbitMQ、Kafka、RPC、Elasticsearch。
欢迎关注作者头条号 张传宁IT讲堂,获取更多IT文章、视频等优质内容。
出处:www.cnblogs.com/SavionZhang
作者:张传宁 技术顾问、培训讲师、微软MCP、系统架构设计师、系统集成项目管理工程师、科技部创新工程师。
专注于企业级通用开发平台、工作流引擎、自动化项目(代码)生成器、SOA 、DDD、 云原生(Docker、微服务、DevOps、CI/CD);PDF、CAD、BIM 审图等研究与应用。
多次参与电子政务、图书教育、生产制造等企业级大型项目研发与管理工作。
熟悉中小企业软件开发过程:可行调研、需求分析、架构设计、编码测试、实施部署、项目管理。通过技术与管理帮助中小企业实现互联网转型升级全流程解决方案。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
如有问题,可以通过邮件905442693@qq.com联系。共同交流、互相学习。
如果您觉得文章对您有帮助,请点击文章右下角【推荐】。您的鼓励是作者持续创作的最大动力!