在 Xamarin UWP 中打印具有多个页面的 WebView
Posted
技术标签:
【中文标题】在 Xamarin UWP 中打印具有多个页面的 WebView【英文标题】:Print WebView with multiple pages in Xamarin UWP 【发布时间】:2018-11-01 03:25:06 【问题描述】:我正在尝试以 xamarin 形式打印网页。我正在使用DependencyService打印webview,我已经在android中成功实现了。
对于 Windows UWP, 我参考了这个链接:https://forums.xamarin.com/discussion/91163/problem-with-printing-webview-in-uwp-phone 这里使用的方法是只打印网页的第一页。
编辑:
我创建了一个接口IPrint
,只提供函数的html源代码。
public interface IPrint
void PrintAsync(string htmlSource);
在 PrintAsync 函数中(在 Windows UWP 项目中),
async void IPrint.PrintAsync(string htmlSource)
ViewToPrint.NavigateToString(htmlSource);
ViewToPrint.LoadCompleted += ViewToPrint_LoadCompleteAsync;
WebView 完全加载后,
private async void ViewToPrint_LoadCompleteAsync(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
if (PrintDoc != null)
printDoc.AddPages -= PrintDoc_AddPages;
printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
printDoc.Paginate -= PrintDoc_Paginate;
this.printDoc = new PrintDocument();
try
printDoc.AddPages += PrintDoc_AddPages;
printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
printDoc.Paginate += PrintDoc_Paginate;
bool showprint = await PrintManager.ShowPrintUIAsync();
catch (Exception ex)
Debug.WriteLine(ex.ToString());
PrintDoc = null;
GC.Collect();
要在 PrintDocument 中添加页面,
private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
printDoc.AddPage(ViewToPrint);
printDoc.AddPagesComplete();
要实现多页打印, 我参考了这个链接:https://***.com/a/17222629/6366591
我将 AddPages 函数更改为以下内容,但它似乎对我不起作用。
private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
rectangleList = GetWebPages(ViewToPrint, new Windows.Foundation.Size(100d, 150d));
foreach (Windows.UI.Xaml.Shapes.Rectangle rectangle in rectangleList)
printDoc.AddPage(rectangle);
printDoc.AddPagesComplete();
您可以在此处找到 GetWebPages() 函数。
List<Windows.UI.Xaml.Shapes.Rectangle> GetWebPages(Windows.UI.Xaml.Controls.WebView webView, Windows.Foundation.Size page)
// ask the content its width
var _WidthString = webView.InvokeScriptAsync("eval",
new[] "document.body.scrollWidth.toString()" ).GetResults();
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:0", _WidthString));
webView.Width = _ContentWidth;
// ask the content its height
var _HeightString = webView.InvokeScriptAsync("eval",
new[] "document.body.scrollHeight.toString()" ).GetResults();
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:0", _HeightString));
webView.Height = _ContentHeight;
// how many pages will there be?
var _Scale = page.Width / _ContentWidth;
var _ScaledHeight = (_ContentHeight * _Scale);
var _PageCount = (double)_ScaledHeight / page.Height;
_PageCount = _PageCount + ((_PageCount > (int)_PageCount) ? 1 : 0);
// create the pages
var _Pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)_PageCount; i++)
var _TranslateY = -page.Height * i;
var _Page = new Windows.UI.Xaml.Shapes.Rectangle
Height = page.Height,
Width = page.Width,
Margin = new Windows.UI.Xaml.Thickness(5),
Tag = new Windows.UI.Xaml.Media.TranslateTransform Y = _TranslateY ,
;
_Page.Loaded += (s, e) =>
var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var _Brush = GetWebViewBrush(webView);
_Brush.Stretch = Windows.UI.Xaml.Media.Stretch.UniformToFill;
_Brush.AlignmentY = Windows.UI.Xaml.Media.AlignmentY.Top;
_Brush.Transform = _Rectangle.Tag as Windows.UI.Xaml.Media.TranslateTransform;
_Rectangle.Fill = _Brush;
;
_Pages.Add(_Page);
return _Pages;
WebViewBrush GetWebViewBrush(Windows.UI.Xaml.Controls.WebView webView)
// resize width to content
var _OriginalWidth = webView.Width;
var _WidthString = webView.InvokeScriptAsync("eval",
new[] "document.body.scrollWidth.toString()" ).GetResults();
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:0", _WidthString));
webView.Width = _ContentWidth;
// resize height to content
var _OriginalHeight = webView.Height;
var _HeightString = webView.InvokeScriptAsync("eval",
new[] "document.body.scrollHeight.toString()" ).GetResults();
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:0", _HeightString));
webView.Height = _ContentHeight;
// create brush
var _OriginalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
var _Brush = new WebViewBrush
SourceName = webView.Name,
Stretch = Windows.UI.Xaml.Media.Stretch.Uniform
;
_Brush.Redraw();
// reset, return
webView.Width = _OriginalWidth;
webView.Height = _OriginalHeight;
webView.Visibility = _OriginalVisibilty;
return _Brush;
【问题讨论】:
您刚刚发布了一部分代码。很难找到问题所在。请提供minimal reproducible example。 我已经编辑了这个问题。希望它能更清楚地描述问题。 【参考方案1】:@Jerry Nixon 的方法对我来说效果很好。由于他的代码示例大约在五年前发布在该线程上。对于当前的 UWP API,我只是做了一些改动(例如,webView.InvokeScriptAsync
)。我还看到您在代码中调用了webView.InvokeScriptAsync
方法。那挺好的。但是你调用GetResults()
方法,我不建议你调用GetResults()
方法。因为调用 javascript 代码有时会花费你很多时间。您可能会收到异常 A method was called at an unexpected time
。
然后,我还注意到您的打印流程有点混乱。请阅读Print from your app了解标准化打印流程。
您可以查看官方代码示例Printing sample了解详细信息。
以下是您的代码 sn-p 的更新代码:
async Task<List<Windows.UI.Xaml.Shapes.Rectangle>> GetWebPages(Windows.UI.Xaml.Controls.WebView webView, Windows.Foundation.Size page)
// ask the content its width
var _WidthString = await webView.InvokeScriptAsync("eval",
new[] "document.body.scrollWidth.toString()" );
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:0", _WidthString));
webView.Width = _ContentWidth;
// ask the content its height
var _HeightString = await webView.InvokeScriptAsync("eval",
new[] "document.body.scrollHeight.toString()" );
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:0", _HeightString));
webView.Height = _ContentHeight;
// how many pages will there be?
var _Scale = page.Width / _ContentWidth;
var _ScaledHeight = (_ContentHeight * _Scale);
var _PageCount = (double)_ScaledHeight / page.Height;
_PageCount = _PageCount + ((_PageCount > (int)_PageCount) ? 1 : 0);
// create the pages
var _Pages = new List<Windows.UI.Xaml.Shapes.Rectangle>();
for (int i = 0; i < (int)_PageCount; i++)
var _TranslateY = -page.Height * i;
var _Page = new Windows.UI.Xaml.Shapes.Rectangle
Height = page.Height,
Width = page.Width,
Margin = new Windows.UI.Xaml.Thickness(5),
Tag = new Windows.UI.Xaml.Media.TranslateTransform Y = _TranslateY ,
;
_Page.Loaded +=async (s, e) =>
var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
var _Brush = await GetWebViewBrush(webView);
_Brush.Stretch = Windows.UI.Xaml.Media.Stretch.UniformToFill;
_Brush.AlignmentY = Windows.UI.Xaml.Media.AlignmentY.Top;
_Brush.Transform = _Rectangle.Tag as Windows.UI.Xaml.Media.TranslateTransform;
_Rectangle.Fill = _Brush;
;
_Pages.Add(_Page);
return _Pages;
async Task<WebViewBrush> GetWebViewBrush(Windows.UI.Xaml.Controls.WebView webView)
// resize width to content
var _OriginalWidth = webView.Width;
var _WidthString = await webView.InvokeScriptAsync("eval",
new[] "document.body.scrollWidth.toString()" );
int _ContentWidth;
if (!int.TryParse(_WidthString, out _ContentWidth))
throw new Exception(string.Format("failure/width:0", _WidthString));
webView.Width = _ContentWidth;
// resize height to content
var _OriginalHeight = webView.Height;
var _HeightString = await webView.InvokeScriptAsync("eval",
new[] "document.body.scrollHeight.toString()" );
int _ContentHeight;
if (!int.TryParse(_HeightString, out _ContentHeight))
throw new Exception(string.Format("failure/height:0", _HeightString));
webView.Height = _ContentHeight;
// create brush
var _OriginalVisibilty = webView.Visibility;
webView.Visibility = Windows.UI.Xaml.Visibility.Visible;
var _Brush = new WebViewBrush
SourceName = webView.Name,
Stretch = Windows.UI.Xaml.Media.Stretch.Uniform
;
_Brush.Redraw();
// reset, return
webView.Width = _OriginalWidth;
webView.Height = _OriginalHeight;
webView.Visibility = _OriginalVisibilty;
return _Brush;
我使用了Printing sample,并将上面更新的代码放入其中并进行了一些相关更改,然后我可以成功打印所有网页。
【讨论】:
你有那个样品吗?我正在尝试在 Xamarin UWP 中执行此操作,但我生成的文档仅是空白页(虽然是多个)。以上是关于在 Xamarin UWP 中打印具有多个页面的 WebView的主要内容,如果未能解决你的问题,请参考以下文章