首页 > 解决方案 > UWP 打印预览仅在第一页显示空白页

问题描述

我们目前正在尝试执行一个功能,该功能将在 gridview 中打印图像(StorageFile存储在模型中。)

我们成功地做到了,但我们遇到了一个我无法弄清楚原因的问题:预览的第一页,而且只有预览!,总是空白。打印(或另存为 PDF)时,它可以完美运行。

出于某种原因,打印预览的加载速度似乎比PrintGenerator.xaml页面中设置的图像快(我们根据需要使用它来放置图像。)

有人有过吗?我尝试了所有我能想到的谷歌搜索,但没有人遇到过这样的问题。

代码:

MainPage.xaml.cs(仅相关行)

private void PrintPages_Click(object sender, RoutedEventArgs e)
{
    if (CurrentPages.Count == 0)
    {
        ShowError(title: "No pages to print", msg: "Please add at least one page to allow printing.");

        return;
    }

    // Name: "PrintPages"
    AppBarButton barButton = (AppBarButton)sender;

    barButton.IsEnabled = false;

    PrintImages();

    barButton.IsEnabled = true;
}
        
private async void PrintImages()
{
    bottomLoader.Visibility = Visibility.Visible;

    if (PrintManager.IsSupported())
    {
        try
        {
            await PrintManager.ShowPrintUIAsync();
        }
        catch (Exception e)
        {
            ShowError(title: "Printing not supported", msg: "Sorry, printing is not supported on this device.\n" + e.Message);
        }
    }
    else
    {
        ShowError(title: "Printing not supported", msg: "Sorry, printing is not supported on this device.");
    }

    bottomLoader.Visibility = Visibility.Collapsed;
}

private PrintManager printManager = PrintManager.GetForCurrentView();

private PrintDocument printDocument = new PrintDocument();

private IPrintDocumentSource printSource;

private List<PrintGenerator> PrintPagePreviews = new List<PrintGenerator>();

private event EventHandler PreviewPagesCreated;

private void RegisterForPrint()
{
    printManager.PrintTaskRequested += PrintStart;

    printSource = printDocument.DocumentSource;

    printDocument.Paginate += PrintPaginate;
    printDocument.GetPreviewPage += PrintPreview;
    printDocument.AddPages += PrintAddPages;
}

private void PrintStart(PrintManager sender, PrintTaskRequestedEventArgs e)
{
    PrintTask task = null;

    task = e.Request.CreatePrintTask("Print", sourceRequestedArgs => {
        IList<string> displayedOptions = task.Options.DisplayedOptions;

        displayedOptions.Clear();
        displayedOptions.Add(StandardPrintTaskOptions.Copies);
        displayedOptions.Add(StandardPrintTaskOptions.Orientation);
        displayedOptions.Add(StandardPrintTaskOptions.MediaSize);
        displayedOptions.Add(StandardPrintTaskOptions.Collation);
        displayedOptions.Add(StandardPrintTaskOptions.Duplex);

        task.Options.MediaSize = PrintMediaSize.NorthAmericaLetter;
        task.Options.PrintQuality = PrintQuality.High;

        task.IsPreviewEnabled = false;
        task.Completed += PrintCompleted;

        sourceRequestedArgs.SetSource(printSource);
    });
}

private void PrintPaginate(object sender, PaginateEventArgs e)
{
    lock (PrintPagePreviews)
    {
        PrintPagePreviews.Clear();

        PrintPageDescription pageDescription = e.PrintTaskOptions.GetPageDescription(0);

        foreach (AppPage fileToPrint in CurrentPages)
        {
            PrintGenerator page = PrintCreatePage(fileToPrint, pageDescription);
            PrintPagePreviews.Add(page);
        }

        if (PreviewPagesCreated != null)
        {
            PreviewPagesCreated.Invoke(PrintPagePreviews, null);
        }

        printDocument.SetPreviewPageCount(PrintPagePreviews.Count, PreviewPageCountType.Intermediate);
    }
}        

private void PrintAddPages(object sender, AddPagesEventArgs e)
{
    foreach (PrintGenerator pagePreview in PrintPagePreviews)
    {
        printDocument.AddPage(pagePreview);
    }

    printDocument.AddPagesComplete();
}

private PrintGenerator PrintCreatePage(AppPage pageFile, PrintPageDescription pageDescription)
{
    PrintGenerator page = new PrintGenerator(pageFile.ImageFile);
    Image img = (Image)page.FindName("ImgPreview");

    page.Width = pageDescription.PageSize.Width;
    page.Height = pageDescription.PageSize.Height;

    double marginWidth = (pageDescription.PageSize.Width - pageDescription.ImageableRect.Width);
    double marginHeight = (pageDescription.PageSize.Height - pageDescription.ImageableRect.Height);

    img.Width = page.Width - marginWidth;
    img.Height = page.Height - marginHeight;
    img.Margin = new Thickness()
    {
        Top = pageDescription.ImageableRect.Top,
        Left = pageDescription.ImageableRect.Left
    };

    page.InvalidateMeasure();
    page.UpdateLayout();

    return page;
}

private void PrintPreview(object sender, GetPreviewPageEventArgs e)
{
    PrintGenerator printPreview = PrintPagePreviews[e.PageNumber - 1];
    printPreview.UpdateLayout();

    printDocument.SetPreviewPage(e.PageNumber, printPreview);
}

private void PrintCompleted(PrintTask sender, PrintTaskCompletedEventArgs e)
{
    if (e.Completion == PrintTaskCompletion.Failed)
    {
        ShowError(title: "Printing error", msg: "Sorry, failed to print.");
    }
    else if (e.Completion == PrintTaskCompletion.Submitted)
    {
        ShowError(title: "Printing success", msg: "Success, task sent to printer.");
    }
}

PrintGenerator.xaml

<Page
    x:Class="COG_ScanDesk.PrintGenerator"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:COG_ScanDesk"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Image x:Name="ImgPreview" HorizontalAlignment="Left" Margin="0" VerticalAlignment="Top" Stretch="Uniform" />
    </Grid>
</Page>

PrintGenerator.xaml.cs

public PrintGenerator(StorageFile file)
{
    this.InitializeComponent();

    LoadImage(file);
}

private async void LoadImage(StorageFile file)
{
    var image = new BitmapImage();
    
    using (var stream = await file.OpenStreamForReadAsync())
    {
        await image.SetSourceAsync(stream.AsRandomAccessStream());
    }

    this.ImgPreview.Source = image;
}

标签: c#windowsprintinguwp

解决方案


出于某种原因,打印预览的加载速度似乎比在 PrintGenerator.xaml 页面中设置的图像要快(我们根据需要使用它来放置图像。)

LoadImage事后处理,对于这种情况,我们建议您像官方代码示例PrintPreview一样重新构建布局,如果您确实想使用上面的代码进行打印预览,您可以像下面这样进行任务延迟。PrintPreview

private async void PrintPreview(object sender, GetPreviewPageEventArgs e)
{
    PrintGenerator printPreview = PrintPagePreviews[e.PageNumber - 1];
    await Task.Delay(500);
    printDocument.SetPreviewPage(e.PageNumber, printPreview);
}

推荐阅读