I have a basic UWP app with an embedded WebView presenting a rather large HTML document (up to 500 letter-sized printed pages).
I'd like to add support for printing that HTML document. Here is my approach:
<div style="height:100vh">
for each "page", up to 500 of these.WebView
on the XAML page that I resize to fit exactly one page based on the user selected page size.scrollY
to show only the current page using JavaScript: window.scrollTo(0, -pageOffset)
WebViewBrush
to capture a snapshot of the current page in the WebView
The problem:
I can generate the print preview of all 500 pages, but sometimes the preview is missing pages while other pages show up multiple times.
I suspect this is because I use WebViewBrush.Redraw()
to capture a snapshot of the scrolled WebView, but the documentation says Redraw()
happens asynchronously. I may scroll past the current page before WebViewBrush gets a chance to redraw, hence accidentally capturing the next page.
How can I make sure that WebViewBrush has captured the WebView so that I can scroll to the next page?
My code to generate a single page:
private async Task<Rectangle> MakePage(WebView webView,
Size pageSize, double pageOffset)
{
// Scroll to next page:
await webView.EvaluateJavaScriptSnippetAsync(
$"window.scrollTo(0, {pageOffset})");
var brush = new WebViewBrush();
brush.Stretch = Stretch.Uniform;
brush.SetSource(webView);
brush.Redraw(); // XXX Need to wait for this, but there's no API
// Add a delay hoping Redraw() finishes... I think here is the problem.
await Task.Delay(150);
var rectangle = new Rectangle()
{
Width = pageSize.Width,
Height = pageSize.Height
};
rectangle.Fill = brush;
brush.Stretch = Stretch.UniformToFill;
brush.AlignmentY = AlignmentY.Top;
return rectangle;
}
Note: If there's an alternative to using WebViewBrush to print 500 pages, I'm open for suggestions. I tried using a separate WebView for each page, but the app runs out of memory after 200 pages.
BOUNTY: I started a bounty offering 100 points to anybody who can figure out how to print 500 pages.
According to the Important section of the WebViewBrush
remarks:
A WebView control has an inherently asynchronous behavior that redraws the control when its content is completely loaded. But an associated WebViewBrush renders as soon as the XAML is parsed (which might be before the URI content is loaded by the WebView ). Alternatively, you can wait to call SetSource on the WebViewBrush until the source content is fully loaded (for example by calling SetSource in the handler for the WebView.LoadCompleted event.
So that you could calling SetSource
method of WebViewBrush
after WebView.LoadCompleted
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With