1. 前言
随着 Web 技术的发展,使用网页内容(HTML、JavaScript、CSS 等)作为桌面应用程序的一部分变得越来越常见。在 C# WinForm 中,Microsoft 提供的 WebView2 控件让我们可以轻松地嵌入 Chromium 浏览器,并实现 C# 与 JavaScript 的互操作。本文将详细介绍如何在 WinForm 项目中集成 WebView2 控件,并实现 C# 和 JavaScript 的双向调用。
2. 前置准备
- 安装 WebView2 Runtime(Windows 11 默认包含)。
- 在项目中添加 WebView2 控件。
- 安装 Microsoft.Web.WebView2 NuGet 包,以支持 WebView2 控件的功能。
3. 初始化 WebView2 控件
在 WinForm 中添加 WebView2 控件并初始化,确保其加载本地或远程的 HTML 文件。
usingMicrosoft.Web.WebView2.Core;usingSystem;usingSystem.Windows.Forms;namespaceWebView2InteropDemo{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();InitializeAsync();}privateasyncvoidInitializeAsync(){await webView21.EnsureCoreWebView2Async(null);string htmlFilePath = System.IO.Path.Combine(AppContext.BaseDirectory,"index.html");
webView21.Source =newUri($"file:///{htmlFilePath.Replace("\\","/")}");}}}
4. JavaScript 调用 C# 方法
实现 JavaScript 调用 C# 的方法需要以下几个步骤:
- 注册一个 C# 对象,使得 JavaScript 可以访问。
- 在 C# 中实现可以调用的公开方法。
- 在 JavaScript 中通过
window.chrome.webview.postMessage
向 C# 发送消息。
C# 端代码
在 WebView2 初始化完成后,可以向 JavaScript 注入一个 C# 对象,提供供调用的方法:
// C# 代码:注册可供 JavaScript 调用的对象publicpartialclassForm1:Form{publicForm1(){InitializeComponent();InitializeAsync();}privateasyncvoidInitializeAsync(){await webView21.EnsureCoreWebView2Async(null);
webView21.CoreWebView2.WebMessageReceived += WebView2_WebMessageReceived;string htmlFilePath = System.IO.Path.Combine(AppContext.BaseDirectory,"index.html");
webView21.Source =newUri($"file:///{htmlFilePath.Replace("\\","/")}");}privatevoidWebView2_WebMessageReceived(object sender,CoreWebView2WebMessageReceivedEventArgs e){string message = e.WebMessageAsJson;// 获取来自 JavaScript 的消息
MessageBox.Show("Received message from JavaScript: "+ message);}// 向 JavaScript 发送消息的 C# 方法publicvoidSendMessageToJavaScript(string message){
webView21.CoreWebView2.PostWebMessageAsString(message);}}
JavaScript 端代码
在 HTML 文件中,通过
window.chrome.webview.postMessage
向 C# 发送消息。首先确保页面加载后,C# 已成功注册监听事件:
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>WebView2 JS to C# Interop</title></head><body><h1>JavaScript to C# Interop</h1><buttononclick="sendMessageToCSharp()">Send Message to C#</button><script>functionsendMessageToCSharp(){// 通过 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 发送消息publicvoidCallJavaScriptFunction(){string script ="displayMessageFromCSharp('Hello from C#');";
webView21.CoreWebView2.ExecuteScriptAsync(script);}
JavaScript 端代码
在 JavaScript 中实现一个函数,用于处理 C# 传递的数据:
<script>functiondisplayMessageFromCSharp(message){alert("Message from C#: "+ message);}</script>
当 C# 调用
CallJavaScriptFunction
方法时,将执行 JavaScript 函数
displayMessageFromCSharp
,并弹出一个消息框显示从 C# 传递的消息。
6. 交互过程总结
- **JavaScript 调用 C#**:
- 通过使用
window.chrome.webview.postMessage
将消息发送到 C#。 - C# 使用
WebMessageReceived
事件接收消息,并在需要时执行相应操作。
- 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代码
namespaceWebView2InteropDemo{partialclassForm1{/// <summary>/// Required designer variable./// </summary>privateSystem.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>protectedoverridevoidDispose(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>privatevoidInitializeComponent(){
webView21 =newMicrosoft.Web.WebView2.WinForms.WebView2();
btnCallJsFunc =newButton();((System.ComponentModel.ISupportInitialize)webView21).BeginInit();SuspendLayout();// // webView21//
webView21.AllowExternalDrop =true;
webView21.CreationProperties =null;
webView21.DefaultBackgroundColor = Color.White;
webView21.Dock = DockStyle.Fill;
webView21.Location =newPoint(0,34);
webView21.Name ="webView21";
webView21.Size =newSize(800,416);
webView21.TabIndex =0;
webView21.ZoomFactor =1D;// // btnCallJsFunc//
btnCallJsFunc.Dock = DockStyle.Top;
btnCallJsFunc.Location =newPoint(0,0);
btnCallJsFunc.Name ="btnCallJsFunc";
btnCallJsFunc.Size =newSize(800,34);
btnCallJsFunc.TabIndex =1;
btnCallJsFunc.Text ="Call Js Func";
btnCallJsFunc.UseVisualStyleBackColor =true;
btnCallJsFunc.Click += btnCallJsFunc_Click;// // Form1//
AutoScaleDimensions =newSizeF(11F,24F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize =newSize(800,450);
Controls.Add(webView21);
Controls.Add(btnCallJsFunc);
Name ="Form1";
StartPosition = FormStartPosition.CenterScreen;
Text ="Form1";((System.ComponentModel.ISupportInitialize)webView21).EndInit();ResumeLayout(false);}#endregionprivateMicrosoft.Web.WebView2.WinForms.WebView2 webView21;privateButton btnCallJsFunc;}}
Form1.cs
usingMicrosoft.Web.WebView2.Core;namespaceWebView2InteropDemo{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();InitializeAsync();}privateasyncvoidInitializeAsync(){await webView21.EnsureCoreWebView2Async(null);
webView21.CoreWebView2.WebMessageReceived += WebView2_WebMessageReceived;string htmlFilePath = System.IO.Path.Combine(AppContext.BaseDirectory,"index.html");
webView21.Source =newUri($"file:///{htmlFilePath.Replace("\\","/")}");}privatevoidWebView2_WebMessageReceived(object sender,CoreWebView2WebMessageReceivedEventArgs e){string message = e.WebMessageAsJson;
MessageBox.Show("Received message from JavaScript: "+ message);}publicvoidSendMessageToJavaScript(string message){
webView21.CoreWebView2.PostWebMessageAsString(message);}publicvoidCallJavaScriptFunction(){string script ="displayMessageFromCSharp('Hello from C#');";
webView21.CoreWebView2.ExecuteScriptAsync(script);}privatevoidbtnCallJsFunc_Click(object sender,EventArgs e){CallJavaScriptFunction();}}}
3、编写html内嵌web网页代码
index.html
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>WebView2 JS to C# Interop</title></head><body><h1>JavaScript to C# Interop</h1><buttononclick="sendMessageToCSharp()">Send Message to C#</button><script>functionsendMessageToCSharp(){
window.chrome.webview.postMessage("Hello from JavaScript!");}functiondisplayMessageFromCSharp(message){alert("Message from C#: "+ message);}</script></body></html>
4、执行结果
JS函数调C#函数代码
C#函数调用JS函数
8.总结
WebView2 的互操作功能使我们能够将现代 Web 技术无缝集成到 WinForm 应用程序中。通过本文介绍的方法,可以实现 JavaScript 和 C# 的双向调用,使得 WinForm 应用程序可以有效地利用 Web 内容和桌面功能,满足更复杂的业务需求。
版权归原作者 dotnet研习社 所有, 如有侵权,请联系我们删除。