Search code examples
c#htmlwinui-3webview2

WinUI3: Get the WebView2 HTML height


I'm currently using a WebView2 in my WinUI3 application to display some HTML which is sent from our server.

The HTML itself doesn't contains a body / html tags and is displayed through NavigateToString:

await web.EnsureCoreWebView2Async();
web.NavigationCompleted += async (sender, args) => await sender.ResizeToContent();  // more about this later
web.NavigateToString(someText);

When I display this HTML in my WebView, the WebView's height is always set at 0 by default, and I want my WebView to autosize to its content (I cannot set a fixed sized for its container and stretch the webview to it).

I tried executing scripts found there to evaluate the HTML's size: How to get height of entire document with JavaScript? :

public static async Task ResizeToContent(this WebView2 webView)
        {
            var script = "";
            var heightString = await webView.ExecuteScriptAsync(script);
            int height = 0;
            if (int.TryParse(heightString, out height))
            {
                webView.Height = height;
            }
        }

Here are 2 differents scripts I tried: eval(document.documentElement.scrollHeight.toString());

and

;(function() {
    var pageHeight = 0;

    function findHighestNode(nodesList) {
        for (var i = nodesList.length - 1; i >= 0; i--) {
            if (nodesList[i].scrollHeight && nodesList[i].clientHeight) {
                var elHeight = Math.max(nodesList[i].scrollHeight, nodesList[i].clientHeight);
                pageHeight = Math.max(elHeight, pageHeight);
            }
            if (nodesList[i].childNodes.length) findHighestNode(nodesList[i].childNodes);
        }
    }

    findHighestNode(document.documentElement.childNodes);
    return pageHeight;

})();

But in both cases, no mater the HTML provided, it always returns 1040 even with a simple HTML such as <p>test</p>

When I set a fixed height for my WebView, let's say of 60, this p is displayed correctly without scrollbar (while my script would return a height of 1040) BUT when I do some complex HTML intended to be bigger than those 60px, the webview displays a vertical scrollbar.

So all in one, it seems the WebView somehow knows that 1040 is not the real height (otherwise I'd have a scrollbar all the time).

Note that I've also tried to surround my text with <html><body>{myText}</body></html> with the same result.

How can I get the real actual content's height?

Thanks.


Solution

  • After trying other solutions, here is what I came up with which seems to work:

    In my ViewModel:

    Text = $"<div id='container'>{_source.Text}</div>";
    

    And in my extension method to get the height:

            public static async Task ResizeToContent(this WebView2 webView)
            {
                var script = "eval(document.getElementById('container').getBoundingClientRect().height.toString());";
                var heightString = await webView.ExecuteScriptAsync(script);
                if (int.TryParse(heightString, out int height))
                {
                    webView.Height = height + 30;
                }
            }
    

    I had to add the +30 because otherwise the scrollbar was displayed and the webview's content slightly truncated.

    Is there any cleaner and less hacky way to do this?