如何访问WebView2控件的Document属性及页面DOM?
WebView2 访问操作DOM解决方案
报错原因
你遇到的CS1061编译错误是两个控件的底层设计差异导致的:
- 旧版
WebBrowser控件基于IE内核封装,直接在.NET层暴露了COM互操作封装的Document属性,可直接在C#侧同步访问DOM WebView2基于Chromium内核,渲染进程和.NET程序进程是隔离的,没有在控件顶层暴露同步的Document属性,所有DOM交互都要通过异步的跨进程通信接口完成,无法直接照搬旧控件的写法。
前置准备
操作DOM前必须确认两个状态:
- WebView2内核初始化完成
- 目标页面加载完成
示例初始化代码:
// 窗体加载或者控件初始化时调用,确保WebView2内核就绪 await webView2.EnsureCoreWebView2Async(); // 监听页面导航完成事件,DOM就绪后再执行操作 webView2.CoreWebView2.NavigationCompleted += async (sender, e) => { if (!e.IsSuccess) return; // 此处编写DOM操作逻辑 };
具体DOM操作实现
官方推荐通过ExecuteScriptAsync方法注入执行JS脚本实现所有DOM操作,等效替代旧版Document属性的所有能力:
1. 获取页面文档内容
如果需要获取整个Document的HTML内容,直接执行JS读取对应属性即可,注意方法返回值是JSON序列化后的字符串,需要反序列化拿到原始值:
// 执行JS获取整个文档HTML string resultJson = await webView2.CoreWebView2.ExecuteScriptAsync("document.documentElement.outerHTML"); // 反序列化得到实际HTML字符串 string documentHtml = System.Text.Json.JsonSerializer.Deserialize<string>(resultJson);
2. 常规DOM增删改查
所有DOM操作都可以直接写在传入的JS脚本里,和前端原生操作DOM写法完全一致,不需要在C#侧持有Document对象:
// 示例:给输入框赋值、点击按钮、读取元素文本 await webView2.CoreWebView2.ExecuteScriptAsync(@" // 查找元素 const userInput = document.querySelector('#username'); // 修改元素值 userInput.value = 'admin'; // 读取元素文本 const tipText = document.querySelector('.tip').innerText; // 触发按钮点击 document.querySelector('#loginBtn').click(); ");
3. DOM事件通知C#侧
如果需要监听DOM事件(比如按钮点击、输入框变化)并回传数据到C#,可以先向JS上下文注入宿主对象,再在JS事件回调里调用宿主对象方法:
// 注入C#侧的交互对象,JS里可通过window.chrome.webview.hostObjects.interactObj访问 webView2.CoreWebView2.AddHostObjectToScript("interactObj", new InteropObject()); // JS侧监听事件调用宿主方法 await webView2.CoreWebView2.ExecuteScriptAsync(@" document.querySelector('#submitBtn').addEventListener('click', () => { // 调用C#对象的方法,传入数据 window.chrome.webview.hostObjects.interactObj.OnSubmit(document.querySelector('#username').value); }); "); // 定义交互类,注意要添加ComVisible特性 [System.Runtime.InteropServices.ComVisible(true)] public class InteropObject { public void OnSubmit(string username) { // C#侧处理DOM事件传回来的数据 MessageBox.Show($"用户提交了用户名:{username}"); } }
注意事项
- 不要尝试通过COM互操作等方式强行获取WebView2的Document对象,Chromium的DOM结构和IE的COM封装完全不兼容,会导致内存泄漏或者进程崩溃
ExecuteScriptAsync是异步方法,必须搭配await关键字调用,不要尝试同步阻塞等待结果,会造成死锁- 不要直接返回DOM节点对象给C#侧,跨进程只支持序列化可JSON编码的值,需要什么属性直接在JS里读取后返回基础类型值即可。
内容的提问来源于stack exchange,提问作者Kim Smith
相关产品推荐
相关产品推荐

