In my app, I have printing working through dependency service in iOS and Android. I found a class here that implemented printing on UWP. However, it only prints one page.
Here is my content page defining the webview:
` public class GroceryListWebView : ContentPage
{
public interface IBaseUrl { string Get(); }
public Command PrintServiceCommand { get; set; } private WebView _browser; private string _htmlSource; public GroceryListWebView(string fileName) { BindingContext = this; var browser = new WebView(); PrintServiceCommand = new Command(Print); //Build webview from html var htmlSource = new HtmlWebViewSource { Html = File.ReadAllText(fileName) }; htmlSource.BaseUrl = DependencyService.Get<IBaseUrl>().Get(); browser.Source = htmlSource; _htmlSource = File.ReadAllText(fileName); _browser = browser; Content = browser; //Build menu for the different platforms switch (Device.RuntimePlatform) { case Device.Android: { var printToolbarItem = new ToolbarItem() { IconImageSource = "print.png", Order = ToolbarItemOrder.Secondary, Priority = 0, Text = "Print" }; printToolbarItem.SetBinding(MenuItem.CommandProperty, "PrintServiceCommand"); ToolbarItems.Insert(0,printToolbarItem); var shareToolbarItem = new ToolbarItem() { IconImageSource = "sharing.png", Order = ToolbarItemOrder.Secondary, Priority = 1, Text = "Sharing" }; shareToolbarItem.SetBinding(MenuItem.CommandProperty, "ShareListCommand"); ToolbarItems.Insert(1, shareToolbarItem); break; } case Device.iOS: { var printToolbarItem = new ToolbarItem() { IconImageSource = "print.png", Order = ToolbarItemOrder.Primary, Priority = 0, Text = "Print" }; printToolbarItem.SetBinding(MenuItem.CommandProperty, "PrintServiceCommand"); ToolbarItems.Insert(0, printToolbarItem); var shareToolbarItem = new ToolbarItem() { IconImageSource = "sharing.png", Order = ToolbarItemOrder.Primary, Priority = 1, Text = "Sharing" }; shareToolbarItem.SetBinding(MenuItem.CommandProperty, "ShareListCommand"); ToolbarItems.Insert(1, shareToolbarItem); break; } case Device.UWP: { var printToolbarItem = new ToolbarItem() { IconImageSource = "print.png", Order = ToolbarItemOrder.Primary, Priority = 0, Text = "Print" }; printToolbarItem.SetBinding(MenuItem.CommandProperty, "PrintServiceCommand"); ToolbarItems.Insert(0, printToolbarItem); var shareToolbarItem = new ToolbarItem() { IconImageSource = "sharing.png", Order = ToolbarItemOrder.Primary, Priority = 1, Text = "Sharing" }; shareToolbarItem.SetBinding(MenuItem.CommandProperty, "ShareListCommand"); ToolbarItems.Insert(1, shareToolbarItem); break; } } } public void Print() { var printService = DependencyService.Get<IPrintService>(); printService.Print(_browser, _htmlSource); } }`
Here is the class I am using for my dependency service:
`[assembly: Dependency(typeof(PrintUwp))]
namespace GroceryList.UWP
{
public class PrintUwp : IPrintService
{
PrintManager printmgr = PrintManager.GetForCurrentView();
PrintDocument PrintDoc;
PrintDocument printDoc;
PrintTask Task;
private Windows.UI.Xaml.Controls.WebView ViewToPrint = new Windows.UI.Xaml.Controls.WebView();
public PrintUwp() { printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested; } public async void Print(WebView viewToPrint, string htmlSource) { ViewToPrint.NavigateToString(htmlSource); if (PrintDoc != null) { printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage; printDoc.Paginate -= PrintDoc_Paginate; printDoc.AddPages -= PrintDoc_AddPages; } printDoc = new PrintDocument(); try { printDoc.GetPreviewPage += PrintDoc_GetPreviewPage; printDoc.Paginate += PrintDoc_Paginate; printDoc.AddPages += PrintDoc_AddPages; var showprint = await PrintManager.ShowPrintUIAsync(); } catch (Exception e) { Debug.WriteLine(e.ToString()); } PrintDoc = null; GC.Collect(); } private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args) { var deff = args.Request.GetDeferral(); Task = args.Request.CreatePrintTask("Grocery List", OnPrintTaskSourceRequested); deff.Complete(); } async void OnPrintTaskSourceRequested(PrintTaskSourceRequestedArgs args) { var def = args.GetDeferral(); await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => { args.SetSource(printDoc.DocumentSource); }); def.Complete(); } private void PrintDoc_AddPages(object sender, AddPagesEventArgs e) { printDoc.AddPage(ViewToPrint); printDoc.AddPagesComplete(); } private void PrintDoc_Paginate(object sender, PaginateEventArgs e) { PrintTaskOptions opt = Task.Options; printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final); } private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e) { printDoc.SetPreviewPage(e.PageNumber, ViewToPrint); } }
}`
I would appreciate any ideas on how to get this to print more than one page from UWP.
John
Answers
Have you checked https://stackoverflow.com/a/50504672/8187800?
The post is incomplete in explaining the entire process of implementing the change. I believe it dealt with creating a UWP native rectangle in XAML and rendering the webview into that and printing. But I don't understand how to make that happen in Xamarin.Forms.
I added the code from here: https://stackoverflow.com/questions/50466333/print-webview-with-multiple-pages-in-xamarin-uwp/50504672://
But I think that code is for a UWP XAML not for Xamarin.Forms UWP, this code does not execute in the lambda expression:
_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; };
So the rectangle is always empty.
Any ideas?
hi @norton287 ,
did you manage to print multiple pages. Im facing the same issue. Can you please let me know. if you have implemented it successfully.
I have printing of multiple pages working. However, I hit an issue trying to package required files into a NuGet. If anybody who knows about building NuGets can assist, I can contribute the code (it's not the older code that's in my GitHub repo).
I ended up just saving the HTML to a file and then launching the default windows browser with the file as the content to open. I can share the code from the UWP project if you want.
Yes. Can you please share the code from UWP project.
Thank you.
Attached are the two files, the interface, and the dependency service file. You just call it from your code with this:
DependencyService.Get<IUWPShare>().HtmlShare(_htmlFile);