WebView2
WebView2和CEF相比,在WPF中CEF相当于把渲染的界面生成图片再加载,而WebView2则没有这一步,性能有显著提升。
但是这种方式暂时没有找到支持Flash的方法。
这种方式可以支持Win7,XP尚未进行测试。
但是在安装的时候64位的Win7竟然无法安装32位的WebView2 运行时,所以建议64位的就安装64位的运行时。
官方教程 https://docs.microsoft.com/zh-cn/microsoft-edge/webview2/get-started/wpf
安装运行时
WebView2 实在诱人,最新的 Edge(Chromium) 性能强悍,而且所有使用 WebView2 的应用可以共用一个运行时(说人话就是一个安装了应用时,其他应用就不用装了)。
Windows 11 已经自带 WebView2 ,就连 Office 也会自动部署 WebView2 ,目前 WebView2 已经被部署到 2亿台电脑,并且还在继续增加 …… 未来是属于 WebView2 的。
重要的是 WebView2 仍然支持老旧的、即将被淘汰的 Windows 7 —— 拥有良好的兼容性。
WebView2是依赖于Edge chromium内核的,有如下三种方式可以获取:
- 安装开发版的Edge (Chromium),稳定版的Edge目前不支持WebView控件,不知道后续会不会开放。
- 安装独立的WebView2 Runtime,它可以独立下载和升级。
- 程序内嵌入Edge chromium内核
这三种方式运行效果基本一致,主要特点是:
前两种方式和以前使用IE的浏览器控件非常类似,浏览器内核和程序是分离的,程序可以保持非常小的体积,浏览器内核可以单独升级。
第一种方式目前还不支持Edge的稳定版,无法使用于生产环境
第三种方式和以前的CEF比较类似,将chromium嵌入了程序,可以控制chromium的版本,减少依赖性,同时可以控制浏览器的版本,避免升级导致的不稳定。
但是相应的程序包会特别大,配置也相对更麻烦。
所以这里我推荐第二种方式。
下载地址:
https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/#download-section
项目使用
使用WebView2
安装Microsoft.Web.WebView2程序包
1 | Install-Package Microsoft.Web.WebView2 |
添加名字空间
1 | xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf" |
添加控件
1 | <wv2:WebView2 Name="webView" Source="https://www.psvmc.cn"/> |
代码设置URL
1 | webView.Source = new Uri("https://www.baidu.com"); |
窗口关闭时要关闭WebView2,否则会报错。
1 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) |
判断运行时是否安装
注意
建议专门一个页面进行检测,检测成功后再跳转到展示页面。
判断是否安装
1 | public static bool IsInstallWebview2() |
安装并重启
1 | /// <summary> |
调用
1 | private async void Window_Loaded(object sender, RoutedEventArgs e) |
其中
1 | ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072; |
是为了解决在Win7环境下载文件报错:
请求被中止: 未能创建 SSL/TLS 安全通道
其中重启应用
1 | Process.Start(Application.ResourceAssembly.Location); |
工具类
1 | using System.Diagnostics; |
加载本地文件
你可以读取HTML文件,然后读取NavigateToString
1 | private void Window_Loaded(object sender, RoutedEventArgs e) |
或者
你也可以通过Navigate
连接到本地文件:
1 | string rootPath = Environment.CurrentDirectory; |
连接使用外部浏览器打开
1 | WebView.NavigationStarting += WebView_NavigationStarting; |
互操作
C#向JS发消息
发送纯文本
本机代码
1 | if (webView != null && webView.CoreWebView2 != null) |
JS代码
1 | <script type="text/javascript"> |
发送JSON
1 | if (webView != null && webView.CoreWebView2 != null) |
JS接收
1 | <script type="text/javascript"> |
唯一的差别在于
接收的时候会自动转换为JSON对象。不过我还是建议传递字符串,转换的操作放在JS中处理。
C#调用JS代码
执行代码
1 | private async void SendBtn_ClickAsync(object sender, RoutedEventArgs e) |
调用JS方法
CSharp
1 | private async void SendBtn_ClickAsync(object sender, RoutedEventArgs e) |
JS中
1 | function receiveMsg (msg) { |
JS如果要修改Vue的data的属性
1 | let vueObj = new Vue({ |
JS调用C#代码
CSharp中定义
定义数据交互的类
1 | [ ] |
代码中注册事件
1 | private void Window_Loaded(object sender, RoutedEventArgs e) |
JS异步调用
异步调用取值
1 | async function myfunc() { |
当然上面的代码也可以简写为
1 | async function myfunc() { |
这是因为我们已经在C#中创建了JS的对象
1 | webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var csobj = window.chrome.webview.hostObjects.csobj;"); |
JS同步调用
同步调用取值
1 | <script type="text/javascript"> |
同步调用
1 | <script type="text/javascript"> |
注意
window.chrome.webview.hostObjects.csobj
是异步的,要想同步就要用window.chrome.webview.hostObjects.sync.csobj
。
打包
程序运行的时候会在根目录生成一个文件夹,类似于xhschool.exe.WebView2
,也就是可执行程序名.WebView2
这个是运行过程中生成的,打包并不需要打包到安装包中,可以设置忽略。
Flash支持
很遗憾,现在还没找到WebView2支持Flash的方式。
目前要想支持Flash只有两种选择:
- 使用Electron加载Flash插件 (Chrome内核)
- 使用
WebBrowser
,系统安装Flash插件(IE内核)
重新渲染
在个别电脑上出现奇葩的问题,网页加载后,页面不渲染。
这里只能通过InvalidateVisual
重新触发渲染。
InvalidateVisual
、InvalidateArrange
和 InvalidateMeasure
是 WPF 中三个不同的方法,用于标记需要进行重新绘制、重新排列和重新测量的元素。
InvalidateVisual
: 该方法用于标记元素和其子元素需要重新绘制视觉呈现。当元素的外观或视觉效果发生改变时,通过调用该方法告诉 WPF 引擎需要更新元素的可视化。比如当一个元素的背景色、边框样式或其他可视化属性改变时,可以调用
InvalidateVisual
来触发重绘操作。InvalidateArrange
: 该方法用于标记元素及其子元素需要进行重新排列。当元素的大小、位置或布局参数发生改变时,通过调用该方法告诉布局系统需要重新计算元素的布局。调用
InvalidateArrange
方法会触发元素的ArrangeOverride
方法,从而实现重新排列。InvalidateMeasure
: 该方法用于标记元素及其子元素需要进行重新测量。当元素的大小或布局参数发生改变时,通过调用该方法告诉布局系统需要重新计算元素的测量。调用
InvalidateMeasure
方法会触发元素的MeasureOverride
方法,从而实现重新测量。
总结来说
InvalidateVisual
用于重新绘制元素的视觉呈现
InvalidateArrange
用于重新排列元素
InvalidateMeasure
用于重新测量元素
它们通常一起使用,以确保元素能够正确地进行绘制、排列和测量,以反映最新的属性或状态的变化。