如何在.NET6 Windows Forms应用中实现BlazorWebView与窗体双向交互
WinForm 与 BlazorWebView 双向通信实现方案
核心思路
通过依赖注入的全局共享服务作为通信中介,无需对接复杂的JS互操作底层接口,实现逻辑更简洁易维护。
步骤1:定义通信服务
先创建公共的服务接口和实现类,用于两端的事件监听和数据传递:
// 通信服务接口 public interface IAppCommunicationService { // WinForm -> Blazor 相关 event Action<string> ReceivedMessageFromWinForm; void SendMessageToBlazor(string message); // Blazor -> WinForm 相关 event Action<string> ReceivedMessageFromBlazor; void SendMessageToWinForm(string message); } // 服务实现类 public class AppCommunicationService : IAppCommunicationService { // WinForm发往Blazor的事件 public event Action<string> ReceivedMessageFromWinForm; public void SendMessageToBlazor(string message) { ReceivedMessageFromWinForm?.Invoke(message); } // Blazor发往WinForm的事件 public event Action<string> ReceivedMessageFromBlazor; public void SendMessageToWinForm(string message) { ReceivedMessageFromBlazor?.Invoke(message); } }
步骤2:注册服务到依赖注入容器
修改你的Program.cs代码,将通信服务注册为全局单例,同时把服务容器暴露为公共静态属性方便后续访问:
// Program.cs public static ServiceProvider ServiceProvider { get; private set; } [STAThread] static void Main() { ApplicationConfiguration.Initialize(); var serviceCollection = new ServiceCollection(); // 新增通信服务注册 serviceCollection.AddSingleton<IAppCommunicationService, AppCommunicationService>(); // 注册BlazorWebView基础服务 serviceCollection.AddBlazorWebView(); ServiceProvider = serviceCollection.BuildServiceProvider(); // 你原有初始化逻辑保持不变 BlazorWebView blazorApp = new BlazorWebView() { Dock = DockStyle.Fill, HostPage = "wwwroot/index.html", Services = ServiceProvider }; blazorApp.RootComponents.Add<App>("#app"); var form1 = new Form1(); form1.Controls.Add(blazorApp); Application.Run(form1); }
步骤3:WinForm 端逻辑实现
修改Form1的代码,实现消息发送和接收逻辑:
public partial class Form1 : Form { private readonly IAppCommunicationService _commService; public Form1() { InitializeComponent(); // 获取通信服务实例 _commService = Program.ServiceProvider.GetRequiredService<IAppCommunicationService>(); // 监听Blazor回传的通知 _commService.ReceivedMessageFromBlazor += OnBlazorMessageReceived; } // 处理Blazor回传的通知 private void OnBlazorMessageReceived(string message) { // 涉及UI操作必须切换到UI线程执行 this.Invoke(() => { MessageBox.Show($"收到Blazor消息:{message}"); }); } // 示例:点击按钮向Blazor发送数据 private void sendToBlazorBtn_Click(object sender, EventArgs e) { _commService.SendMessageToBlazor("这是WinForm发送给Blazor的测试数据"); } // 窗体关闭时取消事件监听避免内存泄漏 protected override void OnFormClosing(FormClosingEventArgs e) { _commService.ReceivedMessageFromBlazor -= OnBlazorMessageReceived; base.OnFormClosing(e); } }
步骤4:Blazor 端逻辑实现
在任意Blazor组件中注入通信服务,实现消息收发:
@inject IAppCommunicationService CommService @implements IAsyncDisposable <p>收到WinForm的消息:@ReceivedMessage</p> <button @onclick="SendToWinForm">给WinForm发通知</button> @code { private string ReceivedMessage { get; set; } protected override void OnInitialized() { // 监听WinForm发送的消息 CommService.ReceivedMessageFromWinForm += OnWinFormMessageReceived; base.OnInitialized(); } private void OnWinFormMessageReceived(string message) { ReceivedMessage = message; // 通知UI更新 StateHasChanged(); } private void SendToWinForm() { CommService.SendMessageToWinForm("这是Blazor回传给WinForm的通知"); } // 组件销毁时取消监听避免内存泄漏 public async ValueTask DisposeAsync() { CommService.ReceivedMessageFromWinForm -= OnWinFormMessageReceived; } }
注意事项
- 如果需要传递复杂类型数据,把上述示例中的
string替换为自定义类即可 - WinForm端所有操作UI控件的逻辑,必须通过
Invoke/BeginInvoke切换到UI线程执行,否则会抛出线程访问异常 - 不再使用的事件监听要及时取消,避免内存泄漏
内容的提问来源于stack exchange,提问作者mz1378
相关产品推荐
相关产品推荐

