WPF 、WebView2 、WebView2 、CoreWebView2 、HostObject 是什么?它们之间有什么关系?
WPF 窗口
这是你的桌面程序的顶层界面容器(Window)。它像一块画布,你把按钮、文本框、WebView2 等控件放到里面显示给用户。
没有窗口的句柄(HWND)时,很多底层控件创建不了,所以通常会在窗口显示/控件加载后再做初始化。
WebView2(WPF 控件)
这是一个可以嵌入浏览器的可视控件,来自 Microsoft.Web.WebView2.Wpf.WebView2。
它负责“显示”网页,是你拖到窗口里的那块区域(UI 层)。
但它本身不包含浏览器内核,必须先调用 EnsureCoreWebView2Async 创建并连接到真正的浏览器内核。
CoreWebView2(浏览器内核实例)
这是 WebView2 控件背后真正的浏览器对象,来自 Microsoft.Web.WebView2.Core.CoreWebView2。
当 EnsureCoreWebView2Async 完成后,webView2.CoreWebView2 才会变为可用。你通过它来:
- 导航网页:CoreWebView2.Navigate(url)
- 执行脚本:CoreWebView2.ExecuteScriptAsync(“…”)
- 订阅事件:NavigationCompleted、NewWindowRequested、DocumentTitleChanged 等注入
- HostObject:CoreWebView2.AddHostObjectToScript(…)
简单理解:WebView2 是“窗户”,CoreWebView2 是“窗外的世界”(浏览器内核),所有交互都在 CoreWebView2 上发生。
HostObject(宿主对象)
它是把你的 .NET/C# 对象“映射”进网页的 JavaScript 环境的桥梁。
你调用 AddHostObjectToScript(“名字”, 对象) 后,网页里就能通过 chrome.webview.hostObjects.名字 调用到你的 C# 方法/属性。
例如:
C#:webView2.CoreWebView2.AddHostObjectToScript("app", new AppBridge());
JS:await chrome.webview.hostObjects.app.DoSomething("参数");
每个 CoreWebView2 都是独立的运行时,新建窗口(新的 CoreWebView2)需要重新 AddHostObjectToScript,否则新窗口里的 JS看不到你的宿主对象。
安全建议:优先用 AddHostObjectToScriptWithOrigins 限定允许访问的来源;或者用 PostWebMessage/MessageReceived 做 JSON 消息通信,更好控权限。
它们之间的关系和生命周期
先有窗口(WPF Window)→ 放入 WebView2 控件 → 调用 EnsureCoreWebView2Async → 生成并拿到 CoreWebView2 → 在 CoreWebView2 上做导航、事件、HostObject 等。
WebView2 控件是一个 UI 包装器;CoreWebView2 是真正的浏览器实例。
新开一个窗口(比如页面 window.open)时,你通常会:
- 创建第二个 WebView2(新的控件)
- 对它再次 EnsureCoreWebView2Async(生成第二个 CoreWebView2)
- 给第二个 CoreWebView2 再注入 HostObject
- 用 ee.NewWindow 把新页面绑定到这个新的 CoreWebView2 上
【一个小例子把它串起来】
- 创建和初始化:
var win = new Window();
var web = new WebView2();
win.Content = web;
win.Show(); // 有句柄后再初始化
await web.EnsureCoreWebView2Async(env); // 初始化浏览器内核
- 使用 CoreWebView2:
web.CoreWebView2.Navigate("https://example.com");
web.CoreWebView2.DocumentTitleChanged += ...;
web.CoreWebView2.AddHostObjectToScript("app", new AppBridge());
- 处理新窗口:
web.CoreWebView2.NewWindowRequested += async (s, e) => {var def = e.GetDeferral(); e.Handled = true; var win2 = new Window(); var web2 = new WebView2(); win2.Content = web2; win2.Show(); await web2.EnsureCoreWebView2Async(env);web2.CoreWebView2.AddHostObjectToScript("app", new AppBridge()); e.NewWindow = web2.CoreWebView2; def.Complete(); };
