在Xamarin UWP中打印包含多个页面的WebView

时间:2018-05-22 11:16:39

标签: printing webview xamarin.uwp

我正在尝试以xamarin形式打印网页。我正在使用DependencyService打印webview,我已经在android中成功实现了。

对于Windows UWP, 我提到了这个链接:
https://forums.xamarin.com/discussion/91163/problem-with-printing-webview-in-uwp-phone
此处使用的方法是仅打印网页的第一页。

修改
我创建了一个接口IPrint,只为函数提供html源代码。

public interface IPrint
{
    void PrintAsync(string htmlSource);
}

在PrintAsync函数中(在Windows UWP项目中),

    async void IPrint.PrintAsync(string htmlSource)
    {
        ViewToPrint.NavigateToString(htmlSource);
        ViewToPrint.LoadCompleted += ViewToPrint_LoadCompleteAsync;
    }

当WebView完全加载时,

    private async void ViewToPrint_LoadCompleteAsync(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
    {

        if (PrintDoc != null)
        {
            printDoc.AddPages -= PrintDoc_AddPages;
            printDoc.GetPreviewPage -= PrintDoc_GetPreviewPage;
            printDoc.Paginate -= PrintDoc_Paginate;
        }
        this.printDoc = new PrintDocument();
        try
        {
            printDoc.AddPages += PrintDoc_AddPages;
            printDoc.GetPreviewPage += PrintDoc_GetPreviewPage;
            printDoc.Paginate += PrintDoc_Paginate;

            bool showprint = await PrintManager.ShowPrintUIAsync();

        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.ToString());
        }
        PrintDoc = null;
        GC.Collect();
    }

在PrintDocument中添加页面

    private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
    {          
        printDoc.AddPage(ViewToPrint);
        printDoc.AddPagesComplete();
    }


要实现多页打印, 我引用了这个链接:https://stackoverflow.com/a/17222629/6366591

我将AddPages功能更改为以下内容,但它似乎对我无效。

    private void PrintDoc_AddPages(object sender, AddPagesEventArgs e)
    {     
        rectangleList = GetWebPages(ViewToPrint,  new Windows.Foundation.Size(100d, 150d));
        foreach (Windows.UI.Xaml.Shapes.Rectangle rectangle in rectangleList)
        {
            printDoc.AddPage(rectangle);
        }                                                                                     
        printDoc.AddPagesComplete();
    }

您可以在此处找到GetWebPages()函数。

    List<Windows.UI.Xaml.Shapes.Rectangle> GetWebPages(Windows.UI.Xaml.Controls.WebView webView, Windows.Foundation.Size page)
    {
        // ask the content its width
        var _WidthString = webView.InvokeScriptAsync("eval",
            new[] { "document.body.scrollWidth.toString()" }).GetResults();
        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 = webView.InvokeScriptAsync("eval",
            new[] { "document.body.scrollHeight.toString()" }).GetResults();
        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 Windows.UI.Xaml.Thickness(5),
                Tag = new Windows.UI.Xaml.Media.TranslateTransform { Y = _TranslateY },
            };
            _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;
            };
            _Pages.Add(_Page);
        }
        return _Pages;
    }

    WebViewBrush GetWebViewBrush(Windows.UI.Xaml.Controls.WebView webView)
    {
        // resize width to content
        var _OriginalWidth = webView.Width;
        var _WidthString = webView.InvokeScriptAsync("eval",
            new[] { "document.body.scrollWidth.toString()" }).GetResults();
        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 = webView.InvokeScriptAsync("eval",
            new[] { "document.body.scrollHeight.toString()" }).GetResults();
        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 = Windows.UI.Xaml.Media.Stretch.Uniform
        };
        _Brush.Redraw();

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

1 个答案:

答案 0 :(得分:0)

@Jerry Nixon的方法在我身边运作良好。因为他的代码示例大约五年前发布在该线程上。对于当前的UWP API,我只做了一些改动(例如,webView.InvokeScriptAsync)。我还看到你在代码中调用了webView.InvokeScriptAsync方法。这很好。但是你调用了GetResults()方法,我没有建议你调用GetResults()方法。因为调用javascript代码有时会花费你很多时间。您可能会收到例外A method was called at an unexpected time

然后,我也注意到你的打印流程有点混乱。请阅读Print from your app以了解标准化打印流程。

您可以查看官方代码示例Printing sample了解详情。

以下是您的代码段的更新代码:

async Task<List<Windows.UI.Xaml.Shapes.Rectangle>> GetWebPages(Windows.UI.Xaml.Controls.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 Windows.UI.Xaml.Thickness(5),
                Tag = new Windows.UI.Xaml.Media.TranslateTransform { Y = _TranslateY },
            };
            _Page.Loaded +=async (s, e) =>
            {
                var _Rectangle = s as Windows.UI.Xaml.Shapes.Rectangle;
                var _Brush = await 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;
            };
            _Pages.Add(_Page);
        }
        return _Pages;
}

    async Task<WebViewBrush> GetWebViewBrush(Windows.UI.Xaml.Controls.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 = Windows.UI.Xaml.Media.Stretch.Uniform
        };
        _Brush.Redraw();

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

我使用Printing sample并将上面更新的代码放入其中并进行一些相关更改,然后我就可以成功打印所有网页。