如何通过WebView2在JS和WPF之间进行通信



最近我们接到通知,由于未来计划相关的原因,我们将使用ReactJs为我们的产品实施新组件。但是,我们将依赖WebView2来在当前WPF应用程序中呈现这些组件。

我们面临的挑战之一是如何在react组件和WPF应用程序之间实现two-way communication

我的团队曾考虑使用SignalR作为主机和组件之间的中介来实现通信,但不确定这是否是这种情况下的最佳解决方案。

是的,WebView2invoke脚本针对组件提供了一种便利,但这将实现从WPF应用程序到react组件的单向通信。

因此,现在需要的是如何实现反之亦然,从react组件调用一些东西来对抗WPF应用程序。对于这种情况,有什么更好的解决方案吗?

对于那些感兴趣的人,我刚刚在NuGet.org上发布了WebView2.DevTools.Dom。任何人都可以免费使用。

Readme中的更多详细信息和示例。

您可以向JavaScript应用程序公开一个函数以进行调用。

await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.DOMContentLoaded += async (s, e) =>
{
var devToolsContext = await webView.CoreWebView2.CreateDevToolsContextAsync();
await devToolsContext.ExposeFunctionAsync("jsAlertButtonClick", () =>
{
_ = devToolsContext.EvaluateExpressionAsync("window.alert('Hello! You invoked window.alert()');");
});
await devToolsContext.ExposeFunctionAsync("csAlertButtonClick", () =>
{
Dispatcher.InvokeAsync(() =>
{
WindowState = WindowState switch
{
WindowState.Maximized => WindowState.Normal,
WindowState.Normal => WindowState.Maximized,
_ => WindowState.Minimized,
};
});
});
var meaningOfLifeAsInt = await devToolsContext.EvaluateFunctionAsync<int>("() => Promise.resolve(42)");
var jsAlertButton = await devToolsContext.QuerySelectorAsync("#jsAlertButton");
var csAlertButton = await devToolsContext.QuerySelectorAsync("#csAlertButton");
_ = jsAlertButton.AddEventListenerAsync("click", "jsAlertButtonClick");
_ = csAlertButton.AddEventListenerAsync("click", "csAlertButtonClick");
var innerText = await jsAlertButton.GetPropertyValueAsync<string>("innerText");
var currentTimeSpan = await devToolsContext.QuerySelectorAsync("#current-time");
var fpsSpan = await devToolsContext.QuerySelectorAsync("#fps");
await devToolsContext.ExposeFunctionAsync<double, bool>("requestAnimationFrameCallback", (highResTime) =>
{
var duration = NodaTime.Duration.FromNanoseconds(Math.Round(highResTime * 1000) * 1000);
callback(duration);
return false;
});
callback(NodaTime.Duration.Zero);
void callback(NodaTime.Duration timestamp)
{
_ = currentTimeSpan.SetInnerText(GetCurrentDateTime());
_ = fpsSpan.SetInnerText(CalculateFps(timestamp).ToString());
_ = devToolsContext.EvaluateExpressionAsync(@"window.requestAnimationFrame((x) => { window.requestAnimationFrameCallback(x)});");
}
};

函数在导航中保持不变,因此您只需要注册一次函数。

上提供了一个工作示例https://github.com/ChromiumDotNet/WebView2.DevTools.Dom/blob/main/WebView2.DevTools.Dom.Wpf.Example/MainWindow.xaml.cs#L22

最新更新