WPF调用Web并且根据接口实时更新数据和切换页面
当时想的需求是WPF有一个模块需要展示数据报表,这个模块可以单独展示也可以集成在WPF主程序中,单独展示碰到一些问题,现在已经解决,特记录一下
方案是,WPF中用WebView2控件展示
1、新建一个Web项目,我这边WPF还有Web都是Core
2、准备工作
- signalr,通信,用来通知Web更新和触发WPF刷新
- Hub,通信中的集线器
- ViewComponent,视图组件,用来返回index嵌套的页面
3、Web操作
- 右键wwwroot,添加,客户端库,提供程序选unpkg,搜索signalr,安装
![]()
-
新增PageController,切换用户组件
// 添加此端点用于前端获取更新的组件 [Route("[controller]")] public class PageController : Controller { [HttpPost("UpdateComponent")] public IActionResult UpdateComponent(int type) { return ViewComponent("Page", type); } }
- 新增DataHub,定义一个集线器(可以这样叫不)
public class DataHub : Hub { public async Task SendDataUpdate(int type) { await Clients.All.SendAsync("ReceiveDataUpdate", type); } }
- 新增DataRefreshService,定时自动刷新
public class DataRefreshService : BackgroundService { private readonly IHubContext<DataHub> _hub; private readonly ApiService apiService; public DataRefreshService(IHubContext<DataHub> hub, IHttpClientFactory httpClientFactory) { _hub = hub; apiService = new ApiService(httpClientFactory); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // 每5妙获取一次最新数据 var freshData = await apiService.GetReportInfo();//这是接口获得的数据 int rt = 0;//0不更新;1更新 if (TypeTool.currentType != freshData.type) { rt = 1; TypeTool.currentType = freshData.type;//TypeTool.currentType用来刷新组件的时候传值 } await _hub.Clients.All.SendAsync("ReceiveDataUpdate", rt); await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } } }
- 新增PageViewComponent,主界面切换嵌套内容的时候,根据参数匹配
public class PageViewComponent : ViewComponent { public IViewComponentResult Invoke(int type) { try { return SelectViewBasedOnData(type); } catch (Exception) { return SelectViewBasedOnData(-1); } } private IViewComponentResult SelectViewBasedOnData(int type) { return type switch { 0 => View("Type0"), 1 => View("Type1"), -1 => View("DefaultView") }; } }
- 主页面index.cshtml
<div id="container"> @await Component.InvokeAsync("Page", @ViewBag.type) </div> @section Scripts { <script src="~/microsoft/signalr/dist/browser/signalr.min.js"></script> <script> const connection = new signalR.HubConnectionBuilder() .withUrl("/dataHub") .build(); connection.on("ReceiveDataUpdate", (rt) => { if(rt==1) { location.reload(); onContentUpdated(); } }); connection.start(); // 当内容更新时调用(通知WPF调用端更新用) function onContentUpdated() { window.chrome.webview.hostObjects.bridge.RequestRefresh(); } </script> }
- 视图组件目录
![]()
-
program中设置,
builder.Services.AddSignalR(); builder.Services.AddHostedService<DataRefreshService>();//定时服务 app.MapHub<DataHub>("/dataHub");
4、WPF操作
- 新增WebView2控件
<Grid> <wpf:WebView2 Name="webView"></wpf:WebView2> </Grid> - 设置
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); InitializeWebView(); } private async void InitializeWebView() { var env = await CoreWebView2Environment.CreateAsync(); await webView.EnsureCoreWebView2Async(env); webView.Source = new Uri("http://localhost:5001"); // 注册 JS 回调(如果使用方案Signalr通信) webView.CoreWebView2.AddHostObjectToScript("bridge", new JsBridge(this)); } // 刷新方法(供JS调用) public void RefreshWebView() => webView.Reload(); } public class JsBridge { private MainWindow _mainWindow; public JsBridge(MainWindow mainWindow) => _mainWindow = mainWindow; public void RequestRefresh() => _mainWindow.RefreshWebView(); }



浙公网安备 33010602011771号