Xamarin.Forms Printing Webview from UWP Project

norton287norton287 Member ✭✭

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

  • ColeXColeX Member, Xamarin Team Xamurai
  • norton287norton287 Member ✭✭

    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.

  • norton287norton287 Member ✭✭

    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?

Sign In or Register to comment.