WebView2控件应用详解系列博客

.NET桌面程序集成Web网页开发的十种解决方案

.NET混合开发解决方案1 WebView2简介

.NET混合开发解决方案2 WebView2与Edge浏览器的区别

.NET混合开发解决方案3 WebView2的进程模型

.NET混合开发解决方案4 WebView2的线程模型

.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 事件将运行。

导航事件的正常顺序为:

  1. NavigationStarting
  2. SourceChanged
  3. ContentLoading
  4. HistoryChanged
  5. BasicAuthenticationRequested
  6. DOMContentLoaded
  7. NavigationCompleted

以下事件描述每次导航操作期间 WebView2 的状态:

上图显示了在各自的事件参数上具有相同NavigationId属性的导航事件。

  • 使用导航ID(在NavigationId事件中提供)跟踪每个新文档的导航事件。每次成功导航到新文档时,WebView2的NavigationId事件都会发生更改。
  • 具有不同NavigationId事件实例的导航事件可能会重叠。例如,启动导航事件时,必须等待相关的NavigationStarting事件。如果随后启动另一个导航,您将看到以下序列:
    1. 第一次导航的 NavigationStarting 事件。
    2. 第二次导航的 NavigationStarting 事件。
    3. 第一次导航的 NavigationCompleted 事件。
    4. 第二次导航的所有其他相应导航事件。
  • 在错误情况下,可能有或可能没有内容加载事件,这取决于导航是否继续导航到错误页面。
  • 如果发生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行。

.NET混合开发解决方案9 WebView2控件的导航事件的更多相关文章

  1. .NET混合开发解决方案10 WebView2控件调用网页JS方法

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  2. .NET混合开发解决方案15 WebView2控件集成到WinForm程序编译后的文件及结构说明

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  3. .NET混合开发解决方案11 WebView2加载的网页中JS调用C#方法

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  4. .NET混合开发解决方案14 WebView2的基本身份验证

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  5. .NET混合开发解决方案24 WebView2对比CefSharp的超强优势

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  6. 混合开发 webview 中file 控件 点击后无反应解决方法

    最近在做个项目 ,需要 使用 file 控件上传 图片到服务器 ,在手机浏览器中 可以正常选择照片,但是放到 android 应用中的webview中,file 控件点击后就没有反应. 百度了一番后, ...

  7. .NET混合开发解决方案5 WebView2运行时与分发应用

    系列目录     [已更新最新开发文章,点击查看详细] 发布使用Microsoft Edge WebView2的应用程序时,客户端计算机上需要安装WebView2运行时,可以安装自动更新的Evergr ...

  8. .NET混合开发解决方案13 自定义WebView2中的上下文菜单

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  9. .NET混合开发解决方案16 管理WebView2的用户数据

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

随机推荐

  1. Redis 的同步机制了解么?

    Redis 可以使用主从同步,从从同步.第一次同步时,主节点做一次 bgsave, 并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制 节点,复制节点接受完成后将 r ...

  2. Maven的Scored介绍

    Maven的Scored值的介绍:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.ht ...

  3. 什么是 Spring beans?

    Spring beans 是那些形成 Spring 应用的主干的 java 对象.它们被 Spring IOC 容器初始化,装配,和管理.这些 beans 通过容器中配置的元数据创建.比如, 以 XM ...

  4. Linux 安装jdk1.8

    Linux安装jdk1.8 总结一句话就是:下载jdk1.8 ==> 解压 ==> 配置环境变量. 一.  jdk的下载,这里有两种方法: 1.去Oracle官网下载. 2.jdk1.8的 ...

  5. TCP 重传、滑动窗⼝、流量控制、拥塞控制

    重传机制 TCP 会在以下两种情况发⽣超时重传: 数据包丢失 确认应答丢失 重传超时 重传超时是TCP协议保证数据可靠性的另一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果 ...

  6. servlet中的HttpServletRequest对象

    HttpServletRequest对象表示客户端浏览器发起的请求,当客户端浏览器通过HTTP协议访问服务器时,Tomcat会将HTTP请求中的所有信息解析并封装在HttpServletRequest ...

  7. 直接使用sublime编译stylus

    stylus介绍 Stylus 是一个CSS的预处理框架,2010年产生,来自Node.js社区,主要用来给Node项目进行CSS预处理支持,所以 Stylus 是一种新型语言,可以创建健壮的.动态的 ...

  8. vue报错解决方案

    Vue build faild 解决办法: https://blog.csdn.net/u011169370/article/details/83346176 ? jbcmVideo git:(oah ...

  9. CTFHUB之gopher协议实现SSRF

    介绍 解题思路: 利用302协议(重定向)的跳转ssrf.可以访问与服务器相连的内网 ①什么是gopher协议 Gopher是Internet上一个信息查找系统,它将Internet上的文件组织成某种 ...

  10. python的编译和解释

    编译和解释 1.编译: 将源代码一次性转换成目标代码的过程 源代码 → 编辑器 →目标代码 →程序执行(同时程序输入)→结果输出 2.解释: 将源代码逐条转换成目标代码同时逐条运行的过程 源代码+程序 ...