WebView2 - 使用 JSON 将 HTML Tbody 转换为集合

WebView2 - Convert HTML Tbody To A Collection Using JSON

我的 HTML 页面中有一个 table 需要发送给主机。我使用 ExecuteScriptAsync 方法 (WebView2) 来做到这一点。那个方法returns一个Newtonsoft.Json.Linq.JObject结果。它看起来像这样 {{ "1": {}, "2": {}, "3": {}, "4": {}, "5": {}, "6": {}, "7": {} }} 。行数是正确的,但如您所见,您没有对 table.

的完全访问权限

反序列化 JObject 以获得 table

的正确方法是什么
JsonConvert.DeserializeObject<object>(await this.WebView2Form.ExecuteScriptAsync("document.getElementById('" + TABLEID + "')." + rows));

换句话说,我需要执行下面的javascript并且能够在C#中读取结果

document.getElementById("myTable").rows

ExecuteScriptAsync 使用 JSON.stringify 将脚本执行的结果序列化为 JSON。在您的浏览器中,如果您导航到带有 table 的页面,例如 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table,然后打开 DevTools 和 运行 以下内容,您会看到相同类型的结果:

JSON.stringify(document.getElementById("perfCardTable").rows)
"{\"0\":{},\"1\":{},\"2\":{},\"3\":{},\"4\":{}}"

问题是 JSON.stringify 仅直接在对象上序列化 hasOwnProperty 属性,而不是从其父对象原型继承的属性。几乎每个 DOM 对象都从其父对象继承其所有属性,因此您会看到 {} 作为任何 DOM 对象的 JSON.stringify 的结果。

要解决此问题,您可以将您关心的属性直接复制到新对象上。

JSON.stringify(Array.from(document.getElementById("perfCardTable").rows).map(row => { 
    let copy = {};
    for (let name in row) {
        copy[name] = row[name];
    }
    return copy;
}));

这样做的结果非常大,并且只处理行上的属性而不是那些属性的属性,因此您可能希望挑选出您感兴趣的特定属性,而不是复制所有内容。

顺便说一句,如果 JSON.stringify 确实序列化了所有继承的属性,如果您给它一个 table 行 DOM 对象,它就会抛出异常,因为它有一个 ownerDocument 属性。 ownerDocument 是包含文档,它允许您获取其子项并最终返回到您的 table 行 DOM 元素,这是 JSON.stringify.

不允许的循环引用

嗯,@David Risney 解释得很好,为什么你不能将 HTMLCollectionrows 属性 returns)序列化为 JSON.

您可以改为编写一个 javascript 函数,该函数 returns 一个二维数组,它将自动序列化为 JSON 并轻松反序列化回二维数组C# 中的数组。

我假设您想将所有单元格的文本作为数组读取。

这样的函数在这里:

var TableContent = function (tableId)
{
    let array = [];

    /** @type {NodeListOf<HTMLTableRowElement>} */
    let rows = document.querySelectorAll('#' + tableId + ' > tbody > tr');

    rows.forEach(function (row, i, rows)
    {
        array[i] = [];
        Array.from(row.cells).forEach(function (cell, j, cells)
        {
            array[i][j] = cell.textContent;
        });
    });
    return array;
};

(你知道如何将 javascript 注入 WebView2)。

现在在 C# 中很容易获得数组:

string tableId = "GridView1";
string json = await webView21.ExecuteScriptAsync("TableContent('" + tableId + "')");
string[][] cellsContent = Newtonsoft.Json.JsonConvert.DeserializeObject<string[][]>(json);

现在你有一个包含所有单元格文本的二维字符串数组。

您可以这样访问:

cellsContent[rowIndex][cellIndex]