.NET混合开发解决方案9 WebView2控件的导航事件


系列目录    

WebView2控件应用详解系列博客

 

  在我的博客中介绍了WinForm程序中集成WebView2组件的详细步骤以及注意事项。这只是最基本的应用,WebView2功能之所以强大,是因为它提供了很多开放的属性与事件供开发者调用以完成复杂的功能。具体可以参考我的博客。

  本文介绍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行。

系列目录