WebView2簡(jiǎn)介
概述
WebView2 全稱 Microsoft Edge WebView2 控件,此控件的作用是在本機(jī)桌面應(yīng)用中嵌入web技術(shù)(html,css,javascript),從名字就可以看出來WebView2使用了Edge內(nèi)核渲染web內(nèi)容。
通俗來說,WebView2控件是一個(gè)UI組件,允許在桌面應(yīng)用中提供web能力的集成,即俗稱的混合開發(fā)。
優(yōu)勢(shì)
- 助力程序開發(fā)和維護(hù):相比桌面應(yīng)用開發(fā),一般來說web技術(shù)更加的靈活
- 無需升級(jí):以往增加了新功能都需要升級(jí)客戶現(xiàn)場(chǎng)的桌面應(yīng)用程序,引入web技術(shù)之后,省去了升級(jí)的煩惱
- 擴(kuò)展web應(yīng)用:補(bǔ)足了web技術(shù)的短板,不能或者很難和宿主機(jī)交互,訪問操作系統(tǒng)api。
支持的運(yùn)行時(shí)平臺(tái)
- Win32 C/C++
- .NET Framework 4.5 或更高版本
- .NET Core 3.1 或更高版本
- .NET 5
- .NET 6
- WinUI 2.0
- WinUI 3.0
進(jìn)程模型
當(dāng)在WPF程序中引入 WebView2 控件后,WPF程序和WebView2控件的進(jìn)程模型如下:
- WPF程序進(jìn)程和WebView2控件是進(jìn)程隔離的
- 維護(hù)WebView2運(yùn)行的實(shí)際是一組進(jìn)程
基本使用
本文代碼基于 .NetFramework 4.8
安裝WebView2運(yùn)行時(shí)
開發(fā)之前需要先安裝WebView2的運(yùn)行時(shí)。
同理,當(dāng)程序開發(fā)完畢,在客戶機(jī)器上面部署WPF應(yīng)用程序的時(shí)候也應(yīng)該先安裝WebView2運(yùn)行時(shí),此部分將放在部署環(huán)節(jié)詳細(xì)討論。
有三種方式安裝WebView2運(yùn)行時(shí):
- 常青版引導(dǎo)程序:就是一個(gè)小的引導(dǎo)程序,方便傳輸,但是下載的時(shí)候需要公網(wǎng)環(huán)境。WebView2運(yùn)行時(shí)實(shí)際通過此引導(dǎo)程序完成安裝。
- 常青版獨(dú)立安裝程序:完整安裝包,可離線安裝
- 已修復(fù)版本:特定版本安裝
WebView2運(yùn)行時(shí)下載:https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/
安裝WebView2Sdk
通過 Nuget 安裝
- 名字:Microsoft.Web.WebView2
- 安裝命令:NuGet\Install-Package Microsoft.Web.WebView2 -Version 1.0.1518.46
- 作者:Microsoft
打開一個(gè)網(wǎng)頁(yè)
新建WPF應(yīng)用程序,并通過如下代碼在Window中添加WebView2 XAML 的命名空間。
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
引入WebView2控件,并設(shè)置 Source 屬性為 https://www.microsoft.com
<Grid>
<wv2:WebView2 Name="wv2" Source="https://www.microsoft.com" />
</Grid>
運(yùn)行程序,將可以看到WPF程序中打開了巨硬官網(wǎng)
通過代碼控制打開的網(wǎng)頁(yè)
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.wv2.Source = new Uri("http://baidu.com");
}
導(dǎo)航事件
導(dǎo)航事件是巨硬官方的一個(gè)叫法,通俗來說就是在WebView2中打開一個(gè)網(wǎng)址的步驟。
打開一個(gè)網(wǎng)頁(yè)的過程
- NavigationStarting:開始導(dǎo)航,導(dǎo)航生成網(wǎng)絡(luò)請(qǐng)求。 主機(jī)可能會(huì)在事件期間禁止請(qǐng)求
- SourceChanged:開始導(dǎo)航,導(dǎo)航生成網(wǎng)絡(luò)請(qǐng)求。 主機(jī)可能會(huì)在事件期間禁止請(qǐng)求
- ContentLoading:開始加載新頁(yè)面的內(nèi)容。
- HistoryChanged:歷史記錄更新
- BasicAuthenticationRequested
- DOMContentLoaded:完成對(duì) DOM 內(nèi)容的分析,但尚未完成加載頁(yè)面上的所有圖像、腳本和其他內(nèi)容。
- NavigationCompleted:完成在新頁(yè)面上加載內(nèi)容。
可通過委托的方式攔截各個(gè)事件:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.wv2.Source = new Uri("http://baidu.com");
//this.wv2.Source = new Uri("about:blank");
//導(dǎo)航開始
this.wv2.NavigationStarting += wv2_NavigationStarting;
//源已經(jīng)更改
this.wv2.SourceChanged += Wv2_SourceChanged;
//內(nèi)容加載中
this.wv2.ContentLoading += Wv2_ContentLoading;
//導(dǎo)航結(jié)束
this.wv2.NavigationCompleted += Wv2_NavigationCompleted;
}
private void Wv2_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
{
throw new NotImplementedException();
}
private void Wv2_ContentLoading(object sender, CoreWebView2ContentLoadingEventArgs e)
{
throw new NotImplementedException();
}
private void Wv2_SourceChanged(object sender, CoreWebView2SourceChangedEventArgs e)
{
throw new NotImplementedException();
}
private void wv2_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
{
throw new NotImplementedException();
}
更改url的過程
更改url的過程依然遵循上述步驟,只是稍微復(fù)雜了一些.
空url
某些情況下,可能需要一個(gè)默認(rèn)的頁(yè)面,那么空url是一個(gè)很好的選擇。
this.wv2.Source = new Uri("about:blank");
進(jìn)階使用
WPF和Web通信
概述
當(dāng)web頁(yè)面中點(diǎn)擊一個(gè)按鈕需要通知WPF宿主程序,或者向WPF傳遞一些指令和數(shù)據(jù)的時(shí)候,需要用到 postMessage 和 WebMessageReceived 。
-
postMessage 是 js 方法,位于 window.chrome.webview.postMessage ,當(dāng)需要向WPF程序發(fā)送數(shù)據(jù)的時(shí)候,只需要調(diào)用此方法,并傳遞參數(shù)就可以。此方法僅在WebView2控件內(nèi)部有用,在Edge中調(diào)用將報(bào)異常(Cannot read properties of undefined ‘postMessage’)
-
WebMessageReceived 是 c# 事件,位于 Microsoft.Web.WebView2.Wpf.WebView2??赏ㄟ^委托此事件來接收web網(wǎng)頁(yè)中發(fā)送過來的消息。
Html代碼示例
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>TestWebView2</title>
</head>
<body>
</br></br></br></br></br>
<button type="button" onclick="postMsg()">給WPF宿主程序發(fā)送msg</button>
<script>
window.onload = function () {
//alert("onload-success");
}
function postMsg() {
var args = "msg ,from webView2";
window.chrome.webview.postMessage(args);
alert("發(fā)送成功,內(nèi)容:" + args);
}
</script>
</body>
</html>
C#代碼示例
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//this.wv2.Source = new Uri("http://baidu.com");
//this.wv2.Source = new Uri("about:blank");
this.wv2.Source = new Uri("file:///E:/code/WPF/ramble-wpf/RambleWPF/html/PostMessage.html");
this.wv2.WebMessageReceived += Wv2_WebMessageReceived;
}
private void Wv2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
//接收到的字符串
string msg = e.TryGetWebMessageAsString();
//接收到的json
string msgJson = e.WebMessageAsJson;
}
常見問題
解決程序安裝到C盤導(dǎo)致Webview2無法打開網(wǎng)頁(yè)問題
現(xiàn)象
如果將源代碼放到C盤并在VS中調(diào)試或者將打包好的程序放到C盤啟動(dòng),都會(huì)發(fā)生無法打開網(wǎng)頁(yè)的問題。
原因
此問題的原因是文件權(quán)限問題,WebView2在工作的時(shí)候需要指定一個(gè)文件夾來存放臨時(shí)文件和數(shù)據(jù),即UserDataFloder,需要此文件夾的讀寫權(quán)限。若不顯示指定udf,將會(huì)在程序啟動(dòng)文件同級(jí)目錄新建一個(gè) RambleWPF.exe.WebView2 的文件夾存放臨時(shí)文件,RambleWPF為WPF應(yīng)用程序的名字。
解決辦法
解決辦法有兩個(gè):
- 顯示指定非系統(tǒng)盤下文件夾作為UDF。比如D:\wvUDF ,需要確保此盤符一定存在,還有特殊的情況,有些操作系統(tǒng)的系統(tǒng)盤可能不是C盤,而是D盤。
- 程序啟動(dòng)的時(shí)候修改默認(rèn)UDF的文件夾權(quán)限,這個(gè)方法看起來有趣,但是可以做到一勞永逸,因?yàn)榉椒?總有破綻。
顯示指定UDF
通過設(shè)置 WebView2控件的CreationProperties屬性可以實(shí)現(xiàn)自定義UDF。
需要注意的是,必須在WebView2.CoreWebView2對(duì)象初始化之前設(shè)置UDF,那么CoreWebView2對(duì)象什么時(shí)候初始化呢?有以下方式:
- 在xaml中設(shè)置 WebView2 的Source 屬性
- 在代碼中手動(dòng)設(shè)置 Source,如 this.wv2.Source= new Uri(“http://baidu.com”)
- 調(diào)用 WebView2.EnsureCoreWebView2Async 方法
示例代碼如下:
public partial class WebView2Demo : Window
{
public WebView2Demo()
{
InitializeComponent();
InitializeAsync();
}
async void InitializeAsync()
{
wv2.CreationProperties = new Microsoft.Web.WebView2.Wpf.CoreWebView2CreationProperties
{
UserDataFolder = "D:\\A\\wvUDF"
};
await wv2.EnsureCoreWebView2Async();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.wv2.Source = new Uri("http://baidu.com");
}
}
提升默認(rèn)UDF文件夾權(quán)限
在程序啟動(dòng)的時(shí)候提升默認(rèn)UDF的讀寫權(quán)限
示例代碼如下:
/// <summary>
/// 給 WebView2Bug.exe.WebView2 文件夾賦予寫入權(quán)限
/// </summary>
private void InitWebView2DirAccess()
{
try
{
string path = AppDomain.CurrentDomain.BaseDirectory;
string webview2DataDir = path + "WebView2Bug.exe.WebView2";
DirectoryInfo dir = new DirectoryInfo(webview2DataDir);
System.Security.AccessControl.DirectorySecurity security = dir.GetAccessControl();
//給文件夾追加 Everyone 的寫入權(quán)限
security.AddAccessRule(new System.Security.AccessControl.FileSystemAccessRule("Everyone", System.Security.AccessControl.FileSystemRights.Write, AccessControlType.Allow));
dir.SetAccessControl(security);
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
上述代碼有點(diǎn)偏激,僅作為參考,實(shí)際開發(fā)中,不應(yīng)該為EveryOne 用戶提升如此大的權(quán)限。
引用
-
WebView2運(yùn)行時(shí)下載:https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/
-
官網(wǎng)教程:https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/文章來源:http://www.zghlxwxcb.cn/news/detail-778532.html
-
C盤權(quán)限問題issues:https://github.com/MicrosoftEdge/WebView2Feedback/issues/3087文章來源地址http://www.zghlxwxcb.cn/news/detail-778532.html
技術(shù)交流
- 郵箱:cnaylor@163.com
- QQ群:1158377441
到了這里,關(guān)于WPF中使用WebView2控件的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!