教你在.Net8.0的WinForm中使用WebView2,实现C#和JavaScript的实时双向互操作

在这里插入图片描述

1. 前言

随着 Web 技术的发展,使用网页内容(HTML、JavaScript、CSS 等)作为桌面应用程序的一部分变得越来越常见。在 C# WinForm 中,Microsoft 提供的 WebView2 控件让我们可以轻松地嵌入 Chromium 浏览器,并实现 C# 与 JavaScript 的互操作。本文将详细介绍如何在 WinForm 项目中集成 WebView2 控件,并实现 C# 和 JavaScript 的双向调用。

2. 前置准备

  1. 安装 WebView2 Runtime(Windows 11 默认包含)。
  2. 在项目中添加 WebView2 控件。
  3. 安装 Microsoft.Web.WebView2 NuGet 包,以支持 WebView2 控件的功能。

3. 初始化 WebView2 控件

在 WinForm 中添加 WebView2 控件并初始化,确保其加载本地或远程的 HTML 文件。

using Microsoft.Web.WebView2.Core;
using System;
using System.Windows.Forms;

namespace WebView2InteropDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeAsync();
        }

        private async void InitializeAsync()
        {
            await webView21.EnsureCoreWebView2Async(null);
           string htmlFilePath = System.IO.Path.Combine(AppContext.BaseDirectory, "index.html");
webView21.Source = new Uri($"file:///{htmlFilePath.Replace("\", "/")}");
        }
    }
}

4. JavaScript 调用 C# 方法

实现 JavaScript 调用 C# 的方法需要以下几个步骤:

  1. 注册一个 C# 对象,使得 JavaScript 可以访问。
  2. 在 C# 中实现可以调用的公开方法。
  3. 在 JavaScript 中通过 window.chrome.webview.postMessage 向 C# 发送消息。
C# 端代码

在 WebView2 初始化完成后,可以向 JavaScript 注入一个 C# 对象,提供供调用的方法:

// C# 代码:注册可供 JavaScript 调用的对象
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        InitializeAsync();
    }

    private async void InitializeAsync()
    {
        await webView21.EnsureCoreWebView2Async(null);
        webView21.CoreWebView2.WebMessageReceived += WebView2_WebMessageReceived;
       string htmlFilePath = System.IO.Path.Combine(AppContext.BaseDirectory, "index.html");
webView21.Source = new Uri($"file:///{htmlFilePath.Replace("\", "/")}");
    }

    private void WebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
    {
        string message = e.WebMessageAsJson; // 获取来自 JavaScript 的消息
        MessageBox.Show("Received message from JavaScript: " + message);
    }

    // 向 JavaScript 发送消息的 C# 方法
    public void SendMessageToJavaScript(string message)
    {
        webView21.CoreWebView2.PostWebMessageAsString(message);
    }
}
JavaScript 端代码

在 HTML 文件中,通过 window.chrome.webview.postMessage 向 C# 发送消息。首先确保页面加载后,C# 已成功注册监听事件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebView2 JS to C# Interop</title>
</head>
<body>
    <h1>JavaScript to C# Interop</h1>
    <button onclick="sendMessageToCSharp()">Send Message to C#</button>

    <script>
        function sendMessageToCSharp() {
            // 通过 WebView2 的 postMessage 将消息发送给 C#
            window.chrome.webview.postMessage("Hello from JavaScript!");
        }
    </script>
</body>
</html>

在此示例中,点击按钮将调用 JavaScript 中的 sendMessageToCSharp() 函数,该函数通过 window.chrome.webview.postMessage 向 C# 发送消息,C# 收到消息后在弹窗中显示接收到的内容。

5. C# 调用 JavaScript 方法

在某些情况下,我们希望从 C# 向 JavaScript 发送消息或调用 JavaScript 函数。可以使用 ExecuteScriptAsync 方法实现此功能。

C# 端代码

在 C# 端调用 ExecuteScriptAsync 来执行 JavaScript 代码:

// C# 代码:向 JavaScript 发送消息
public void CallJavaScriptFunction()
{
    string script = "displayMessageFromCSharp('Hello from C#');";
    webView21.CoreWebView2.ExecuteScriptAsync(script);
}
JavaScript 端代码

在 JavaScript 中实现一个函数,用于处理 C# 传递的数据:

<script>
    function displayMessageFromCSharp(message) {
        alert("Message from C#: " + message);
    }
</script>

当 C# 调用 CallJavaScriptFunction 方法时,将执行 JavaScript 函数 displayMessageFromCSharp,并弹出一个消息框显示从 C# 传递的消息。

6. 交互过程总结

  1. JavaScript 调用 C#
  • 通过使用 window.chrome.webview.postMessage 将消息发送到 C#。
  • C# 使用 WebMessageReceived 事件接收消息,并在需要时执行相应操作。
  1. C# 调用 JavaScript:
  • 通过使用 ExecuteScriptAsync 方法执行 JavaScript 代码。
  • JavaScript 端实现处理函数,接受从 C# 传递的消息或参数,并做出响应。

7.完整项目构建汇总

1、新增项目WebView2InteropDemo,并且引入依赖库
引入依赖库

根据操作系统版本,引入WebView2.Runtime.X64
在这里插入图片描述

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <Nullable>disable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="WebView2.Runtime.X64" Version="130.0.2849.80" />
  </ItemGroup>

  <ItemGroup>
    <None Update="index.html">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>
2、新增Form1窗体,构建布局

在这里插入图片描述

Form1.Designer.cs代码
namespace WebView2InteropDemo
{
    partial class Form1
    {
        /// <summary>
        ///  Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        ///  Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        ///  Required method for Designer support - do not modify
        ///  the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            webView21 = new Microsoft.Web.WebView2.WinForms.WebView2();
            btnCallJsFunc = new Button();
            ((System.ComponentModel.ISupportInitialize)webView21).BeginInit();
            SuspendLayout();
            // 
            // webView21
            // 
            webView21.AllowExternalDrop = true;
            webView21.CreationProperties = null;
            webView21.DefaultBackgroundColor = Color.White;
            webView21.Dock = DockStyle.Fill;
            webView21.Location = new Point(0, 34);
            webView21.Name = "webView21";
            webView21.Size = new Size(800, 416);
            webView21.TabIndex = 0;
            webView21.ZoomFactor = 1D;
            // 
            // btnCallJsFunc
            // 
            btnCallJsFunc.Dock = DockStyle.Top;
            btnCallJsFunc.Location = new Point(0, 0);
            btnCallJsFunc.Name = "btnCallJsFunc";
            btnCallJsFunc.Size = new Size(800, 34);
            btnCallJsFunc.TabIndex = 1;
            btnCallJsFunc.Text = "Call Js Func";
            btnCallJsFunc.UseVisualStyleBackColor = true;
            btnCallJsFunc.Click += btnCallJsFunc_Click;
            // 
            // Form1
            // 
            AutoScaleDimensions = new SizeF(11F, 24F);
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(800, 450);
            Controls.Add(webView21);
            Controls.Add(btnCallJsFunc);
            Name = "Form1";
            StartPosition = FormStartPosition.CenterScreen;
            Text = "Form1";
            ((System.ComponentModel.ISupportInitialize)webView21).EndInit();
            ResumeLayout(false);
        }

        #endregion

        private Microsoft.Web.WebView2.WinForms.WebView2 webView21;
        private Button btnCallJsFunc;
    }
}
Form1.cs
using Microsoft.Web.WebView2.Core;

namespace WebView2InteropDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            InitializeAsync();
        }

        private async void InitializeAsync()
        {
            await webView21.EnsureCoreWebView2Async(null);
            webView21.CoreWebView2.WebMessageReceived += WebView2_WebMessageReceived;
            string htmlFilePath = System.IO.Path.Combine(AppContext.BaseDirectory, "index.html");
            webView21.Source = new Uri($"file:///{htmlFilePath.Replace("\", "/")}");
        }

        private void WebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
        {
            string message = e.WebMessageAsJson;
            MessageBox.Show("Received message from JavaScript: " + message);
        }

        public void SendMessageToJavaScript(string message)
        {
            webView21.CoreWebView2.PostWebMessageAsString(message);
        }

        public void CallJavaScriptFunction()
        {
            string script = "displayMessageFromCSharp('Hello from C#');";
            webView21.CoreWebView2.ExecuteScriptAsync(script);
        }

        private void btnCallJsFunc_Click(object sender, EventArgs e)
        {
            CallJavaScriptFunction();
        }
    }
}
3、编写html内嵌web网页代码

在这里插入图片描述

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebView2 JS to C# Interop</title>
</head>
<body>
    <h1>JavaScript to C# Interop</h1>
    <button onclick="sendMessageToCSharp()">Send Message to C#</button>

    <script>
        function sendMessageToCSharp() {
            window.chrome.webview.postMessage("Hello from JavaScript!");
        }

        function displayMessageFromCSharp(message) {
            alert("Message from C#: " + message);
        }
    </script>
</body>
</html>
4、执行结果
JS函数调C#函数代码

在这里插入图片描述

C#函数调用JS函数

在这里插入图片描述

8.总结

WebView2 的互操作功能使我们能够将现代 Web 技术无缝集成到 WinForm 应用程序中。通过本文介绍的方法,可以实现 JavaScript 和 C# 的双向调用,使得 WinForm 应用程序可以有效地利用 Web 内容和桌面功能,满足更复杂的业务需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值