Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I print WebView content C# UWP Win 10

Tags:

I've searched how to print a simple WebView as :

 <WebView x:Name="MyWebView" Source="http://www.stackoverflow.com" />

I tried many things as :

How do I print WebView content in a Windows Store App?

This solution is sadly not updated for Windows 10 UWP apps, but, I converted it so the obsoletes functions would work that leads me to another problem.

To print, I used some classes from the sample (Windows-universal-samples/Samples/Printing/cs/) because I need the preview. I put the example given in the above mentioned question as :

<RichTextBlock
    x:Name="TextContent"
    Grid.Row="1"
    Grid.ColumnSpan="2"
    Width="595"
    HorizontalAlignment="Center"
    VerticalAlignment="Top"
    Foreground="Black"
    IsTextSelectionEnabled="True"
    OverflowContentTarget="{Binding ElementName=FirstLinkedContainer}">
        <Paragraph>
            <InlineUIContainer> [The question XAML]

The overflow is not managed, and so the WebView is seen like this : enter image description here Note: I'm new to XAML language and the logic behind this.

I would like an update on how to do this and if this is possible ?

EDIT:

Here's the code behind of my PageToPrint.xaml.cs :

using System;
using System.Collections.Generic;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace TestPrint
{
    /// <summary>
    /// Page content to send to the printer
    /// </summary>
    public sealed partial class PageToPrint : Page
    {
        public RichTextBlock TextContentBlock { get; set; }

        public PageToPrint()
        {
            this.InitializeComponent();
            TextContentBlock = TextContent;
            MyWebView.LoadCompleted += MyWebView_LoadCompletedAsync;
        }

        async void MyWebView_LoadCompletedAsync(object sender, NavigationEventArgs e)
        {
            MyWebViewRectangle.Fill = await GetWebViewBrushAsync(MyWebView);
            MyPrintPages.ItemsSource = await GetWebPagesAsync(MyWebView, new Windows.Foundation.Size(100d, 150d));
            MyWebView.Visibility = Windows.UI.Xaml.Visibility.Visible;
        }

        async System.Threading.Tasks.Task<WebViewBrush> GetWebViewBrushAsync(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 = Stretch.Uniform
            };
            _Brush.Redraw();

            // reset, return
            webView.Width = _OriginalWidth;
            webView.Height = _OriginalHeight;
            webView.Visibility = _OriginalVisibilty;
            return _Brush;
        }

        async System.Threading.Tasks.Task<IEnumerable<FrameworkElement>> GetWebPagesAsync(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 Thickness(5),
                    Tag = new TranslateTransform { Y = _TranslateY },
                };
                _Page.Loaded += async (s, e) =>
                {
                    var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
                    var _Brush = await GetWebViewBrushAsync(webView);
                    _Brush.Stretch = Stretch.UniformToFill;
                    _Brush.AlignmentY = AlignmentY.Top;
                    _Brush.Transform = _Rectangle.Tag as TranslateTransform;
                    _Rectangle.Fill = _Brush;
                };
                _Pages.Add(_Page);
            }
            return _Pages;
        }
    }
}
like image 647
RamenTurismo Avatar asked Sep 27 '17 15:09

RamenTurismo


People also ask

Does window print work on mobile?

It is not supported on Android." Android phones don't have native support for printing yet, so window. print() will not work.


1 Answers

For your requment, I simplified the PrintHelper of official sample and created a simple sample to print WebView via use WebViewBrush.

<Page.BottomAppBar>
    <CommandBar>
        <AppBarButton
            x:Name="appbar_Printer"
            Click="appbar_Printer_Click"
            Label="printer" />
    </CommandBar>
</Page.BottomAppBar>

<Grid x:Name="PrintArea" Background="White">

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="995" />
        <ColumnDefinition Width="300" />
        <ColumnDefinition  Width="50"/>

    </Grid.ColumnDefinitions>

    <WebView Grid.Column="0" x:Name="MyWebView" Source="http://www.stackoverflow.com" HorizontalAlignment="Right" />
    <Rectangle Grid.Column="1" x:Name="MyWebViewRectangle" Fill="Red" />
    <Button Grid.Column="2" Content="Print"  HorizontalAlignment="Center"/>

</Grid>

When the WebView load completed, you could add the MyWebViewRectangle that fill with WebViewBrush to printDoc.

private async void appbar_Printer_Click(object sender, RoutedEventArgs e)
{
    if (printDoc != null)
    {
        printDoc.GetPreviewPage -= OnGetPreviewPage;
        printDoc.Paginate -= PrintDic_Paginate;
        printDoc.AddPages -= PrintDic_AddPages;
    }
    this.printDoc = new PrintDocument();
    printDoc.GetPreviewPage += OnGetPreviewPage;
    printDoc.Paginate += PrintDic_Paginate;
    printDoc.AddPages += PrintDic_AddPages;
    bool showPrint = await PrintManager.ShowPrintUIAsync();
}
private void PrintDic_AddPages(object sender, AddPagesEventArgs e)
{
    Rectangle page = (Rectangle)this.FindName("MyWebViewRectangle");
    printDoc.AddPage(page);
    printDoc.AddPagesComplete();
}
private void PrintDic_Paginate(object sender, PaginateEventArgs e)
{
    PrintTaskOptions opt = task.Options;
    PrintTaskOptionDetails printDetailedOptions = PrintTaskOptionDetails.GetFromPrintTaskOptions(e.PrintTaskOptions);

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

enter image description here

I have uploaded the code sample to github that you could refer to.

like image 141
Nico Zhu - MSFT Avatar answered Oct 12 '22 18:10

Nico Zhu - MSFT