0

I want to set WebView to WebViewBrush in order to add inside rectangle and print rectangle. I want to do everything on the backend side, I don't want to use XAML code.

I do this because I get blurry/fuzzy text when I get a print preview. So people say the way to solve this is to create WebViewBrush and then create a rectangle to print that

First I create canvas and brush as:

  private Windows.UI.Xaml.Controls.WebView ViewToPrint = new Windows.UI.Xaml.Controls.WebView();
  private Windows.UI.Xaml.Controls.WebViewBrush wvBrush = new Windows.UI.Xaml.Controls.WebViewBrush();
  private Windows.UI.Xaml.Shapes.Rectangle rectangle = new Windows.UI.Xaml.Shapes.Rectangle();

Then in method I assign WebView to WebViewBrush and add it to a rectangle,

public async void Print(Xamarin.Forms.WebView viewToPrint, string html)
        {
        ViewToPrint.NavigateToString(html);
        wvBrush.SetSource(ViewToPrint);
        wvBrush.Redraw();
        rectangle.Fill = wvBrush;
        rectangle.Width = 200;
        rectangle.Height = 200;

        }

Then inside print preview method I want to see that rectangle preview as:

 private void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
        {
           
            printDoc.SetPreviewPage(e.PageNumber, rectangle);
        }

But my rectangle is blank, I don't see anything inside it. What I'm doing wrong

Reproduce the issue:

Xamarin shared project class:

   private readonly IPrintUWPService _printUWPService = DependencyService.Get<IPrintUWPService>();

   public void Printhtml()
        {
        
   var meta = "<meta name='viewport' content='width=device-width, initial-scale=5.0, maximum-scale=5.0, minimum-scale=1.0'>";
            var style = "<style>svg{height:140px; width:140px;} p{font-size:20px;} </style>";

         var  _htmlSource = @$"
                    <!DOCTYPE html>
                    <html>
                    <head>
                      {meta}
                       {style}
                    </head>
                    <body>
                   <table border = '1px solid'; style='border-collapse:collapse;'>
                    <tbody>
                    <tr>
                    <td>qr</td>
                    <td>
                    <p><b>Heat Number:number</b></p>
                    <p><b> Cylinder Type Name: cylindername</b></p>
                   <p><b> Color: colorname</b></p>
                    </td>
                    </tr>
                    </tbody>
                    </table>
                    </body>
                    </html>
                    ";
          Print(_htmlSource);

        }
     

  public void Print(string _htmlSource)
        {
            _printUWPService.Print( _htmlSource);
        }

Interface in shared project:

public interface IPrintUWPService
    {
        void Print(string html);
    }

UWP project service:

 public class PrintUWPService : IPrintUWPService
    {
        PrintManager printmgr = PrintManager.GetForCurrentView();
        PrintDocument PrintDoc;
        PrintDocument printDoc;
        PrintTask Task;
        private Windows.UI.Xaml.Controls.WebView ViewToPrint = new Windows.UI.Xaml.Controls.WebView();
        private DeviceInformationCollection deviceCollection;
        private Windows.UI.Xaml.Shapes.Rectangle rectangle = new Windows.UI.Xaml.Shapes.Rectangle();


        public PrintUWPService()
        {
            printmgr.PrintTaskRequested += Printmgr_PrintTaskRequested;
        }

        public async void Print(Xamarin.Forms.WebView viewToPrint, string html)
        {


            ViewToPrint.NavigateToString(html);
            //MakePage();


            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 = PrintManager.ShowPrintUIAsync();

            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
            }

            PrintDoc = null;
            GC.Collect();
        }

        private void MakePage()
        {
            var brush = new WebViewBrush
            {
                Stretch = (Windows.UI.Xaml.Media.Stretch)Windows.UI.Xaml.Media.Stretch.Uniform
            };
            
            brush.SetSource(ViewToPrint);
            brush.Redraw();

            using (var waitHandle = new System.Threading.ManualResetEventSlim(initialState: false))
                waitHandle.Wait(TimeSpan.FromMilliseconds(5000));

            rectangle.Width = 200;
            rectangle.Height = 200;
            rectangle.Fill = brush;
            brush.Stretch = (Windows.UI.Xaml.Media.Stretch)Windows.UI.Xaml.Media.Stretch.UniformToFill;
            brush.AlignmentY = AlignmentY.Top;
            rectangle.Name = "MyWebViewRectangle";

            rectangle.Visibility = Windows.UI.Xaml.Visibility.Visible;
        }

        private void Printmgr_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
        {
            var deff = args.Request.GetDeferral();
            Task = args.Request.CreatePrintTask($"Card Stock { DateTime.Now}", 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(rectangle);
            printDoc.AddPagesComplete();
        }

        private async void PrintDoc_Paginate(object sender, PaginateEventArgs e)
        {
            PrintTaskOptions printingOptions = ((PrintTaskOptions)e.PrintTaskOptions);
            deviceCollection =  await DeviceInformation.FindAllAsync("System.Devices.InterfaceClassGuid:=\"{0ecef634-6ef0-472a-8085-5ad023ecbccd}\"");
           var rolloPrinter = deviceCollection.Where(x => x.Name.Contains("Rollo")).SingleOrDefault();

            // Get the page description to deterimine how big the page is
            PrintPageDescription pageDescription = printingOptions.GetPageDescription(0);

            PrintTaskOptions opt = Task.Options;

            printDoc.SetPreviewPageCount(1, PreviewPageCountType.Final);
        }

        private  void PrintDoc_GetPreviewPage(object sender, GetPreviewPageEventArgs e)
        {
            printDoc.SetPreviewPage(e.PageNumber, rectangle);
        }

      
    }
Jason
  • 45
  • 6

1 Answers1

0

Fill rectangle with WebView data

Derive from your description, it looks you have not rendered rectangle in the xaml before call print api. And insert it into printDoc pages. Please refer this case reply and render rectangle at first.

Rectangle page = (Rectangle)this.FindName("MyWebViewRectangle");
printDoc.AddPage(page);
printDoc.AddPagesComplete();

Update

During checking your code, I found the reason, the problem is you have not rendered your the WebView in the visual tree that make is WebViewBrush not work. It's often necessary to call Redraw for a WebViewBrush that's declared in XAML in the same UI as is the WebView source. For more please refer this.

And you could use the following line to verify this.

public void Print(string html)
{
    // render current ViewToPrint
    Window.Current.Content = ViewToPrint;
    ViewToPrint.NavigateToString(html);

    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 = PrintManager.ShowPrintUIAsync();

    }
    catch (Exception e)
    {
        Debug.WriteLine(e.ToString());
    }

    //PrintDoc = null;
    //GC.Collect();
}
  
Nico Zhu
  • 32,367
  • 2
  • 15
  • 36
  • I didn't use XAML on the service. So I can't use "this.FindName", that's why I use rectangle as global variable. So I try: `Windows.UI.Xaml.Shapes.Rectangle page = (Windows.UI.Xaml.Shapes.Rectangle)rectangle; printDoc.SetPreviewPage(e.PageNumber, page);` But is the same thing. Blank page – Jason Mar 18 '21 at 16:47
  • Does it render in your current content? – Nico Zhu Mar 19 '21 at 01:25
  • If I use `ViewToPrint.NavigateToString(html);` directly as: `printDoc.SetPreviewPage(e.PageNumber, ViewToPrint);` it works, I get the print view correctly but with blurry problem, so I want to convert it to rectangle to solve it – Jason Mar 19 '21 at 01:33
  • I think the rectangle need to be rendered before print. – Nico Zhu Mar 19 '21 at 01:41
  • But rectangle is rendered when service is called because it is global variable or am I wrong? – Jason Mar 19 '21 at 01:48
  • Could you mind share a [mcve], and I will test base on your code sample. – Nico Zhu Mar 19 '21 at 01:50
  • I can see the change, it loads the HTML on the page, but not in print preview. In the print preview is still with blank page, I mean appears that the brush does not work with rectangle – Jason Mar 19 '21 at 05:39
  • it could show the rectangle in my side. please check this [screenshot](https://i.stack.imgur.com/XRSig.png). – Nico Zhu Mar 19 '21 at 06:14
  • how??? did you change something in rectangle create? in my app does not work! can you share your current brush code please? – Jason Mar 19 '21 at 23:25
  • Sure, please check this [code sample](https://github.com/ZhuMingHao/PrintTest). – Nico Zhu Mar 20 '21 at 07:40
  • The rectangle works now, but that does not solve the main problem.. that prevents blurry/fuzzy content, it still fuzzy :( – Jason Mar 20 '21 at 21:43