0
votes

We are currently trying to do a function that will print the images in a gridview (StorageFile is stored in the model.)

We successfully did it, but we got one issue that I just can't figure the reason why: the first page of the preview, and the preview only!, is always blank. When printed (or saved as PDF), it works perfectly.

For some reason, it seems the print preview loads faster than the image is set in the PrintGenerator.xaml page (which we use to put the image, as required.)

Does anyone ever had that? I tried every Google search I could think of and no one had that precise problem.

CODE:

MainPage.xaml.cs (relevant lines only)

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

1 Answers

1
votes

For some reason, it seems the print preview loads faster than the image is set in the PrintGenerator.xaml page (which we use to put the image, as required.)

It looks LoadImage method after PrintPreview event, for this scenario, we suggest you re-build layout like official code sample , And if you do want to use above code to make print preview, you could make task delay in the PrintPreview like the following.

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