Печать WebView с несколькими страницами в Xamarin UWP

Abhishek Aggarwal спросил: 28 апреля 2018 в 09:36 в: printing

Я пытаюсь распечатать веб-страницу в форматах xamarin. Я использую DependencyService для печати webview, который я успешно реализовал в android.

Для Windows UWP я ссылался на эту ссылку: https://forums.xamarin.com/discussion/91163/ проблема-с-печать-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 ().

1 ответ

Xavier Xie - MSFT ответил: 30 апреля 2018 в 06:55

Метод Джерри Никсона хорошо работал на моей стороне. Так как его образец кода был опубликован в этой теме около пяти лет назад. Для текущих API UWP я просто сделал небольшие изменения (например, webView.InvokeScriptAsync). Я также видел, что вы вызываете метод webView.InvokeScriptAsync в своем коде. Это хорошо. Но вы вызываете метод GetResults(), я не предлагаю вам вызвать метод GetResults(). Потому что иногда код javascript требует много времени. Вы можете получить исключение A method was called at an unexpected time.

Затем я также заметил, что ваш поток печати немного беспорядок. Пожалуйста, прочитайте "Печать" из своего приложения, чтобы изучить стандартизованный процесс печати. ​​

Вы можете проверить пример официального образца образца для печати. ​​

Ниже приведен обновленный код фрагмента кода:

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

Я использовал образец печати и поместил в него мой обновленный код и сделал некоторые соответствующие изменения, после чего смог успешно распечатать все веб-страницы.