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行。