Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >WPF开发-使用WebView2加载页面及页面交互

WPF开发-使用WebView2加载页面及页面交互

作者头像
码客说
发布于 2022-06-12 04:37:47
发布于 2022-06-12 04:37:47
10.1K00
代码可运行
举报
文章被收录于专栏:码客码客
运行总次数:0
代码可运行

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内核的,有如下三种方式可以获取:

  1. 安装开发版的Edge (Chromium),稳定版的Edge目前不支持WebView控件,不知道后续会不会开放。
  2. 安装独立的WebView2 Runtime,它可以独立下载和升级。
  3. 程序内嵌入Edge chromium内核

这三种方式运行效果基本一致,主要特点是:

  • 前两种方式和以前使用IE的浏览器控件非常类似,浏览器内核和程序是分离的,程序可以保持非常小的体积,浏览器内核可以单独升级。
  • 第一种方式目前还不支持Edge的稳定版,无法使用于生产环境
  • 第三种方式和以前的CEF比较类似,将chromium嵌入了程序,可以控制chromium的版本,减少依赖性,同时可以控制浏览器的版本,避免升级导致的不稳定。 但是相应的程序包会特别大,配置也相对更麻烦。

所以这里我推荐第二种方式。

下载地址:

https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/#download-section

项目使用

安装WebView2

安装Microsoft.Web.WebView2程序包

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Install-Package Microsoft.Web.WebView2

添加名字空间

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"

添加控件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<wv2:WebView2 Name="webView" Source="https://www.psvmc.cn"/>

判断运行时是否安装

注意

建议专门一个页面进行检测,检测成功后再跳转到展示页面。

判断是否安装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static bool IsInstallWebview2()
{
  string result = "";
  try
  {
    result = CoreWebView2Environment.GetAvailableBrowserVersionString();
  }
  catch (System.Exception)
  {
  }
  if (result == "" || result == null)
  {
    return false;
  }
  return true;
}

检测并安装

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private async Task InstallRuntimeAsync()
{
  // 解决下载文件报错:请求被中止: 未能创建 SSL/TLS 安全通道
  ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
  var webClient = new WebClient();
  bool isDownload = false;
  string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
  string MicrosoftEdgeWebview2Setup = System.IO.Path.Combine(desktopPath, "MicrosoftEdgeWebview2Setup.exe");
  try
  {
    webClient.DownloadFileCompleted += (s, e) =>
    {
      if (e.Error != null)
      {
        MessageBox.Show("下载失败:" + e.Error.Message);
      }
      else if (e.Cancelled)
      {
        MessageBox.Show("下载取消");
      }
      else
      {
        isDownload = true;
      }
    };
    await webClient.DownloadFileTaskAsync("https://go.microsoft.com/fwlink/p/?LinkId=2124703", MicrosoftEdgeWebview2Setup);
  }
  catch (Exception)
  {
  }
  if (isDownload)
  {
    await Task.Delay(300);
    await Task.Run(
      () =>
      {
        Process.Start(MicrosoftEdgeWebview2Setup, " /install").WaitForExit();
      }
    );

    if (IsInstallWebview2())
    {
      if (
        Environment.OSVersion.Version.Major < 6 ||
        Environment.OSVersion.Version.Major == 6 &&
        Environment.OSVersion.Version.Minor <= 1
      )
      {
        //Restart application in Win7 or lower OS
        var location = System.Reflection.Assembly.GetExecutingAssembly().Location;
        location = location.Replace(".dll", ".exe");
        Process.Start(location);
      }
      else
      {
        System.Windows.Forms.Application.Restart();
      }
      Close();
    }
  }
}

调用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
  webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
  sendBtn.Click += SendBtn_ClickAsync;
  await webView.EnsureCoreWebView2Async();
  if (!IsInstallWebview2())
  {
    await InstallRuntimeAsync();
  }
}

其中

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

解决在Win7环境下载文件报错:

请求被中止: 未能创建 SSL/TLS 安全通道

重启应用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (
  Environment.OSVersion.Version.Major < 6 ||
  Environment.OSVersion.Version.Major == 6 &&
  Environment.OSVersion.Version.Minor <= 1
)
{
  //Restart application in Win7 or lower OS
  var location = System.Reflection.Assembly.GetExecutingAssembly().Location;
  location = location.Replace(".dll", ".exe");
  Process.Start(location);
}
else
{
  System.Windows.Forms.Application.Restart();
}
Close();

加载本地文件

你可以读取HTML文件,然后读取NavigateToString

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void Window_Loaded(object sender, RoutedEventArgs e)
{
  webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
  webView.EnsureCoreWebView2Async();
}

private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
  string rootPath = Environment.CurrentDirectory;
  string filepath = System.IO.Path.Combine(rootPath, "html", "index.html");
  Console.WriteLine(filepath);
  if (webView != null && webView.CoreWebView2 != null)
  {
    string text = System.IO.File.ReadAllText(filepath);
    webView.CoreWebView2.NavigateToString(text);
  }
}

或者

你也可以通过Navigate连接到本地文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
string rootPath = Environment.CurrentDirectory;
string filepath = System.IO.Path.Combine(rootPath, "html", "index.html");
webView.Source = new Uri("file:///" + filepath);

互操作

C#向JS发消息

本机代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (webView != null && webView.CoreWebView2 != null)
{
  webView.CoreWebView2.PostWebMessageAsString(inputTB.Text);
}

JS代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
  window.chrome.webview.addEventListener('message', arg => {
    document.querySelector(".outer").innerHTML = arg.data;
  });
</script>

或者发送JSON

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (webView != null && webView.CoreWebView2 != null)
{
  webView.CoreWebView2.PostWebMessageAsJson("{\"color\":\"blue\"}");
}

JS接收

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
  window.chrome.webview.addEventListener('message', arg => {
    document.querySelector(".outer").innerHTML = arg.data.color;
  });
</script>

唯一的差别在于

接收的时候会自动转换为JSON对象。不过我还是建议传递字符串,转换的操作放在JS中处理。

C#调用JS代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private async void SendBtn_ClickAsync(object sender, RoutedEventArgs e)
{
  if (webView != null && webView.CoreWebView2 != null)
  {
    await webView.CoreWebView2.ExecuteScriptAsync("alert('123')");
  }
}

或者调用JS方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function showmsg(msg) {
  alert(msg);
}

本机代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private async void SendBtn_ClickAsync(object sender, RoutedEventArgs e)
{
  if (webView != null && webView.CoreWebView2 != null)
  {
    await webView.CoreWebView2.ExecuteScriptAsync("showmsg('你好')");
  }
}

JS调用C#代码

定义数据交互的类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class ScriptCallbackObject
{
  public string GetMessageInfo()
  {
    return "C#返回的信息";
  }

  public void ShowMessage(string arg)
  {
    Console.WriteLine(arg);
    MessageBox.Show("【网页调用C#】:" + arg);
  }
}

代码中注册事件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void Window_Loaded(object sender, RoutedEventArgs e)
{
  webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
  webView.EnsureCoreWebView2Async();
}

private void WebView_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
  if (webView != null && webView.CoreWebView2 != null)
  {
    //注册csobj脚本c#互操作
    webView.CoreWebView2.AddHostObjectToScript("csobj", new ScriptCallbackObject());
    //注册全局变量csobj
    webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var csobj = window.chrome.webview.hostObjects.csobj;");
    webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var csobj_sync= window.chrome.webview.hostObjects.sync.csobj;");
    
    //加载页面
    string rootPath = Environment.CurrentDirectory;
    string filepath = System.IO.Path.Combine(rootPath, "html", "index.html");
    string text = System.IO.File.ReadAllText(filepath);
    webView.CoreWebView2.NavigateToString(text);
  }
}

HTML中

异步调用取值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
  function myfunc() {
    window.chrome.webview.hostObjects.csobj.GetMessageInfo()
      .then(
        msg => {
          document.querySelector(".mytext").innerText = msg;
        }
    )
  }
</script>

当然上面的代码也可以简写为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function myfunc() {
  csobj.GetMessageInfo()
    .then(
      msg => {
        document.querySelector(".mytext").innerText = msg;
      }
  )
}

这是因为我们已经在C#中创建了JS的对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var csobj = window.chrome.webview.hostObjects.csobj;");

同步调用取值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
  function myfunc() {
    var msg = window.chrome.webview.hostObjects.sync.csobj.GetMessageInfo();
    document.querySelector(".mytext").innerText = msg;
  }
</script>

同步调用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script type="text/javascript">
  function myfunc() {
    window.chrome.webview.hostObjects.sync.csobj.ShowMessage("你好吗");
  }
</script>

注意

window.chrome.webview.hostObjects.csobj是异步的,要想同步就要用window.chrome.webview.hostObjects.sync.csobj

Flash支持

很遗憾,现在还没找到WebView2支持Flash的方式。

目前要想支持Flash只有两种选择:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Winform 使用WebView2 开发现代应用
它允许开发者将现代 Web 技术(如 HTML、CSS 和 JavaScript)与桌面应用相结合,从而构建强大、灵活的用户界面。
郑子铭
2025/02/18
3960
Winform 使用WebView2 开发现代应用
.Net WebView2 项目,实现 嵌入 WEB 页面 Chromium内核
WebView2 项目得天独厚,有微软操作系统win10以及win11的加持,最起码,生成的项目文件是很小的,我这边是3.6M,相对于CefSharp项目动辄100M的大小来讲,大大降低分发的大小,所以还是值得深入研究一下的。
沙漠尽头的狼
2022/06/13
1.5K0
.Net WebView2 项目,实现 嵌入 WEB 页面 Chromium内核
win10 UWP 访问网页 设置代理WebView
Windows10 UWP 要访问 csdn博客,可以使用Windows.Web.Http.HttpClient,下面尝试访问一下我的博客 http://blog.csdn.net/lindexi_gd/article/details/50392343
林德熙
2018/09/18
1.6K0
win10 UWP 访问网页
            设置代理WebView
WPF中WebView2禁用F12和右键菜单
默认WebView2加载网页是可以通过F12和右键打开调试窗口,但是大多情况下我们在发版时要禁用。
码客说
2023/11/22
1.8K0
Electron 吞噬资源,微软 Teams 为性能改用 WebView2
微软近期宣布,旗下 Teams 应用活跃用户已经达到惊人的 2.5 亿。这让 Teams 成了继 Word 和 Excel 之后,微软 Office 生产力套件中的又一位当红明星。然而,Teams 一直受到性能问题的困扰,用户们对此吐槽不断。
HelloGitHub
2021/11/12
3.7K0
.NET混合开发解决方案10 WebView2控件调用网页JS方法
  客户端程序(WinForm、WPF、Win32、WinUI)集成WebView控件加载Web完成后,还有两种常见的需求
张传宁IT讲堂
2022/05/09
3.3K0
.NET混合开发解决方案10 WebView2控件调用网页JS方法
.NET混合开发解决方案9 WebView2控件的导航事件
  在我的博客《.NET混合开发解决方案7 WinForm程序中集成WebView2》中介绍了WinForm程序中集成WebView2组件的详细步骤以及注意事项。这只是最基本的应用,WebView2功能之所以强大,是因为它提供了很多开放的属性与事件供开发者调用以完成复杂的功能。具体可以参考我的博客《.NET混合开发解决方案2 WebView2与Edge浏览器的区别》。
张传宁IT讲堂
2022/05/09
1K0
.NET混合开发解决方案9 WebView2控件的导航事件
跨平台桌面开发,Electron还是WebView2 (上篇)
我在2020年曾经基于Electron开发过一个跨平台桌面应用,在一定的条件下,Electron是非常好的选择。
御剑
2022/03/09
4.2K0
跨平台桌面开发,Electron还是WebView2 (上篇)
.NET混合开发解决方案4 WebView2的线程模型
  WebView2控件基于组件对象模型(COM),必须在单线程单元(STA)线程上运行。
张传宁IT讲堂
2022/05/09
3.4K0
.NET混合开发解决方案4 WebView2的线程模型
.NET混合开发解决方案5 WebView2运行时与分发应用
  发布使用Microsoft Edge WebView2的应用程序时,客户端计算机上需要安装WebView2运行时,可以安装自动更新的Evergreen运行时,也可以安装固定版本的。
张传宁IT讲堂
2022/05/09
1.8K0
.NET混合开发解决方案5 WebView2运行时与分发应用
.NET混合开发解决方案11 WebView2加载的网页中JS调用C#方法
  在我的博客《.NET混合开发解决方案10 WebView2控件调用网页JS方法》中介绍了C#调用网页中定义的JavaScript方法以执行某种业务逻辑,同样WebView2控件中加载的网页中自定义的JavaScript方法中也可以调用C#方法。
张传宁IT讲堂
2022/05/11
11.3K1
.NET混合开发解决方案11 WebView2加载的网页中JS调用C#方法
微软的混合开发解决方案 WebView2
我们都知道对于桌面应用开发来说,人们常用的方式就是采用c++或者c#,java等进行开发,然而这些语言开发效率不够高,不如网页开发灵活。因此,人们思考能否采用html+css+js的方式来开发桌面客户端呢,于是人们就提出了混合开发概念,并且开发了electron框架进行桌面开发。
程序那些事儿
2023/03/07
2K0
微软的混合开发解决方案 WebView2
.NET混合开发解决方案2 WebView2与Edge浏览器的区别
  WebView2 基于Microsoft Edge浏览器。 开发者可以将功能从浏览器扩展到基于 WebView2 的应用。 由于 WebView2 不限于类似浏览器的应用,因此需要修改或删除一些浏览器功能。
张传宁IT讲堂
2022/05/09
1.3K0
.NET混合开发解决方案2 WebView2与Edge浏览器的区别
.NET混合开发解决方案14 WebView2的基本身份验证
  WebView2 应用的基本身份验证包括从 HTTP 服务器检索网页的一系列身份验证和导航步骤。 WebView2 控件充当主机应用和 HTTP 服务器之间通信的中介。
张传宁IT讲堂
2022/05/13
1.8K0
.NET混合开发解决方案14 WebView2的基本身份验证
直播修仙:使用.NET 的 WebView2 如何获取请求的响应内容,以微信直播的互动直播为例
近几年直播行业快速发展,门槛也越来越低,越来越的人涌入直播大军。不得不说,直播不仅带来了更多的娱乐消遣,还提供了一个新型的就业方式。
桑榆肖物
2022/11/18
2.8K0
直播修仙:使用.NET 的 WebView2 如何获取请求的响应内容,以微信直播的互动直播为例
微软偷偷决定不开源 Linux 及 macOS 版 WebView2,网友:等了四年,我还是用 Electron?!
2021 年,有用户曾在 GitHub 上发帖询问微软的 WebView2 组件是否会支持 Linux 和 macOS 系统。WebView2 是微软基于自家 Edge 浏览器打造的开源渲染组件,相当于微软 Edge 浏览器的一个缩小版本。
深度学习与Python
2024/07/24
2770
微软偷偷决定不开源 Linux 及 macOS 版 WebView2,网友:等了四年,我还是用 Electron?!
.NET混合开发解决方案3 WebView2的进程模型
  WebView2 运行时使用与 Microsoft Edge 浏览器相同的进程模型。
张传宁IT讲堂
2022/05/09
9460
.NET混合开发解决方案3 WebView2的进程模型
.NET混合开发解决方案6 检测是否已安装合适的WebView2运行时
  长青版WebView2运行时将作为Windows 11操作系统的一部分包含在内。但是在Windows 11之前(Win10、Win8.1、Win7等),某些设备可能未预安装WebView2运行时。在桌面程序(WinForm、WPF、WinUI、Win32)安装、更新、启动后或创建 WebView2对象之前,程序可以自动执行此检查。通过检查注册表项或调用 API 来检查客户端电脑中是否已经安装了 WebView2 运行时,并在缺少时自动安装它。
张传宁IT讲堂
2022/05/09
2.6K0
.NET混合开发解决方案6 检测是否已安装合适的WebView2运行时
.NET混合开发解决方案13 自定义WebView2中的上下文菜单
对比可以看出WebView2控件中的右键上下文菜单内容比Edge浏览器中网页的右键右键上下文菜单的数量少。结合我的博客《.NET混合开发解决方案2 WebView2与Edge浏览器的区别》可知,WebView2控件中对于网页右键上下文菜单做了裁剪。
张传宁IT讲堂
2022/05/12
3.1K0
.NET混合开发解决方案13 自定义WebView2中的上下文菜单
WPF/WinForm中加载网页的几种方式及如何加载Flash库(WebBrowser/CEF)
https://docs.microsoft.com/zh-cn/microsoft-edge/webview2/get-started/wpf
码客说
2022/06/12
4.1K0
WPF/WinForm中加载网页的几种方式及如何加载Flash库(WebBrowser/CEF)
推荐阅读
相关推荐
Winform 使用WebView2 开发现代应用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验