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.
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?