locked
Xamarin.Forms Printing Webview from UWP Project RRS feed

  • Question

  • User385259 posted

    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

    Tuesday, May 7, 2019 12:37 PM

All replies

  • User369978 posted

    Have you checked https://stackoverflow.com/a/50504672/8187800?

    Tuesday, May 7, 2019 2:09 PM
  • User385259 posted

    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.

    Tuesday, May 7, 2019 2:14 PM
  • User385259 posted

    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?

    Wednesday, May 8, 2019 6:01 PM
  • User396601 posted

    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.

    Wednesday, September 2, 2020 3:07 AM
  • User89714 posted

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

    Wednesday, September 2, 2020 9:38 AM
  • User385259 posted

    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.

    Wednesday, September 2, 2020 11:01 AM
  • User396601 posted

    @norton287 Yes. Can you please share the code from UWP project. Thank you.

    Thursday, September 3, 2020 12:30 AM
  • User385259 posted

    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);

    Thursday, September 3, 2020 1:18 PM