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();
    }

     

 

posted @ 2025-07-10 16:25  我不是白菜啊  阅读(49)  评论(0)    收藏  举报