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

article/2025/8/14 22:51:01

在这里插入图片描述

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);}#endregionprivate 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 内容和桌面功能,满足更复杂的业务需求。


http://www.hkcw.cn/article/XPJGRVxVVR.shtml

相关文章

【多线程初阶】synchronized锁

文章目录 &#x1f305;synchronized关键字&#x1f30a; synchronized 的互斥&#x1f30a; synchronized 的变种写法&#x1f3c4;‍♂️synchronized 修饰代码块 :明确指定锁哪个对象&#x1f3c4;‍♂️synchronized 修饰方法 &#x1f30a; synchronized 的可重入性&#…

使用 Cython 编译将.py文件加密成.so文件

文章目录 1. .so文件的核心意义和优势2. 使用 Cython 编译&#xff0c;将.py文件加密成.so文件 最近在学习在服务器上如何部署Python模型&#xff0c;不学不知道&#xff0c;一学吓一跳&#xff0c;要学好多啊&#xff0c;最近看到什么就记录一下什么吧。 1. .so文件的核心意义…

环赛里木湖公路自行车赛开赛 速度与激情点燃丝路热土

5月31日上午10时,中国新疆第十七届环赛里木湖(国际)公路自行车赛在精河县鸣枪开赛。首段比赛全长83.1公里,以速度与激情点燃了“中国枸杞之乡”精河县的丝路热土。骑手们从精河县出发,沿精阿高速疾驰,穿越艾比湖湿地和甘家湖梭梭林国家级自然保护区。开赛后仅10分钟,在顺…

南京大学通报施工方偷窃物品 施工单位被罚2000元

5月29日,南京大学基本建设处发布了一份关于对南京诚善科技有限公司执行合同违约金的通报。通报指出,南京大学三校区公共区域饮水机采购及安装项目的施工单位南京诚善科技有限公司的一名员工于5月13日在学校宿舍楼内偷窃学生物品。根据施工合同相关规定并经处办公会研究确认,…

java 反射 枚举与lambda表达式

目录 一.反射 1.概念&#xff1a;在运⾏时检查、访问和修改类、接⼝、字段和⽅法的机制 2.Class类 3.反射相关的类型 4.各类型对应的方法 ​编辑 5.代码示例 (1).class类方法 (2).Field类方法 (3).Constructor类方法 (4).Method类方法 6.总结 二.枚举 1.概念&#x…

【AI大模型】Ollama部署本地大模型DeepSeek-R1,交互界面Open-WebUI,RagFlow构建私有知识库

文章目录 DeepSeek介绍公司背景核心技术产品与服务应用场景优势与特点访问与体验各个DeepSeek-R系列模型的硬件需求和适用场景 Ollama主要特点优势应用场景安装和使用配置环境变量总结 安装open-webui下载和安装docker desktop配置镜像源安装open-webui运行和使用 RagFlow介绍主…

DeepSeek:全栈开发者视角下的AI革命者

无论是想要学习人工智能当做主业营收&#xff0c;还是像我一样作为开发工程师但依然要了解这个颠覆开发的时代宠儿&#xff0c;都有必要了解、学习一下人工智能。 近期发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;入行门槛低&#x…

什么是贝叶斯优化(Bayesian Optimization)?

贝叶斯最优化&#xff08;Bayesian Optimization&#xff09;是一种用于函数全局最优化的策略&#xff0c;特别适用于那些计算代价昂贵的黑箱函数&#xff08;如机器学习模型的超参数调优&#xff09;。其核心思想是通过构建一个代理模型&#xff08;通常是高斯过程或随机森林&…

Spring AI+DeepSeek快速构建AI智能机器人

引言 在AI技术蓬勃发展的当下&#xff0c;Spring生态推出了Spring AI项目&#xff0c;为Java开发者提供了便捷的AI集成方案。本文将演示如何用Spring AIDeepSeek V3 快速搭建一个具备自然语言处理能力的智能对话机器人。 一、环境准备 JDK 17 Maven/Gradle构建工具 DeepSe…

【大模型科普】大模型:人工智能的前沿(一文读懂大模型)

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈人工智能与大模型应用 ⌋ ⌋ ⌋ 人工智能&#xff08;AI&#xff09;通过算法模拟人类智能&#xff0c;利用机器学习、深度学习等技术驱动医疗、金融等领域的智能化。大模型是千亿参数的深度神经网络&#xff08;如ChatGPT&…

借用AI工具(cursor/vscode) 调试matlab代码(2025.4最新实测)

本文实测环境&#xff1a;MATLAB 2025a Windows 11 本文亮点&#xff1a;无需重写Python&#xff01;用AI直接优化现有MATLAB工程 一、AI调试MATLAB的紧迫性 因为matlab无法内置ai 工具 &#xff0c;别人都有的不能out了 另外说一声matlba2025a已经很改版很多了&#xff0c;与…

5 分钟用满血 DeepSeek R1 搭建个人 AI 知识库(含本地部署)

最近很多朋友都在问:怎么本地部署 DeepSeek 搭建个人知识库。 老实说,如果你不是为了研究技术,或者确实需要保护涉密数据,我真不建议去折腾本地部署。 为什么呢? 目前 Ollama 从 1.5B 到 70B 都只是把 R1 的推理能力提炼到 Qwen 和 Llama 的蒸馏版本上。 虽说性能是提升…

灰狼优化算法(GWO)(含ai创作)

GWO简介 灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;GWO&#xff09;是一种模仿灰狼狩猎行为的群体智能优化算法&#xff0c;由Seyedali Mirjalili等人在2014年提出。这种算法主要模拟了灰狼的社会等级结构和狩猎策略&#xff0c;用于解决各种优化问题。 在灰狼…

5步掌握MCP HTTP模式部署:从零开始搭建你的AI“邮局”!

&#x1f525;关注墨瑾轩&#xff0c;带你探索编程的奥秘&#xff01;&#x1f680; &#x1f525;超萌技术攻略&#xff0c;轻松晋级编程高手&#x1f680; &#x1f525;技术宝库已备好&#xff0c;就等你来挖掘&#x1f680; &#x1f525;订阅墨瑾轩&#xff0c;智趣学习不…

基于DeepSeek-Coder,实现Microi吾码低代码平台AI代码辅助生成的思路设想【辅助代码生成】

文章目录 引言一、整体架构设计二、实现流程与关键技术1. 构建领域数据集2. 模型训练与微调3. 生成代码的安全控制4. 平台集成与交互设计 三、效果优化与评估1. 效果展示2. 评估指标 四、未来优化方向结语 引言 低代码开发平台&#xff08;Microi吾码&#xff09;通过可视化交…

【DeepSeek+即梦AI:零基础生成专业级AI图片全流程指南(2025实战版)】

第一部分:工具认知篇——认识你的数字画笔 1.1 工具定位与核心价值 (讲师开场白)各位同学好,今天我们要解锁的是AI创作领域最具生产力的组合工具——DeepSeek+即梦AI。就像画家需要画笔与颜料,这对组合就是你的数字创作套装: • DeepSeek:国内顶尖的智能提示词工程师 …

【Ai学习】利用扣子(Coze)简单搭建图像生成工作流(小白初学版)

开始之前我们先了解一下我们准备使用的工具。 什么是扣子&#xff08;Coze&#xff09;&#xff1f; 官网链接&#xff1a;扣子 扣子&#xff08;Coze&#xff09;是一个开源的AI工具开发平台&#xff0c;提供了丰富的API和简单易用的界面&#xff0c;帮助用户快速搭建各种A…

AIGC时代——语义化AI驱动器:提示词的未来图景与技术深潜

文章目录 一、技术范式重构&#xff1a;从指令集到语义认知网络1.1 多模态语义解析器的进化路径1.2 提示词工程的认知分层 二、交互革命&#xff1a;从提示词到意图理解2.1 自然语言交互的认知进化2.2 专业领域的认知增强 三、未来技术图谱&#xff1a;2025-2030演进路线3.1 20…

【AI 大模型】LlamaIndex 大模型开发框架 ② ( LlamaIndex 可配置的 LLM 类型 | LlamaIndex 可配置的 文本向量模型 类型 )

文章目录 一、LlamaIndex 可配置的 LLM 类型1、云端 API 类型 LLM2、本地部署 类型 LLM3、混合部署 LLM4、错误示例 - 设置 云端 DeepSeek 大模型 二、LlamaIndex 可配置的 文本向量模型 类型1、云端 文本向量模型2、本地部署 文本向量模型3、适配器微调模型 AdapterEmbeddingM…

云端微光,AI启航:低代码开发的智造未来

文章目录 前言一、引言&#xff1a;技术浪潮中的个人视角初次体验腾讯云开发 Copilot1.1 低代码的时代机遇1.1.1 为什么低代码如此重要&#xff1f; 1.2 AI 的引入&#xff1a;革新的力量1.1.2 Copilot 的亮点 1.3 初学者的视角1.3.1 Copilot 带来的改变 二、体验记录&#xff…