microsoft / microsoft/microsoft-ui-xaml
Print Preview does not show image elements
- Dominant language
- C++
- Stars
- 8.4k
- Forks
- 942
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 105
Description
### Describe the bug
(originally from a discussion [on StackOverflow](https://stackoverflow.com/questions/79939304/print-preview-doesnt-show-all-elements), I was advised this is a bug)
I want to print from a WinUI 3 app but am having a problem where images don't always show up. I am following the document [Print from your app](https://learn.microsoft.com/en-us/windows/apps/develop/devices-sensors/print-from-your-app) and the [Coloring Book](https://github.com/microsoft/Windows-appsample-coloringbook) sample.
I am finding that images do not show up on the first page (or sometimes two pages) of the preview, and are also missing from the printout (just using print-to-pdf). The images are just loaded from local URLs in the Assets folder. I suspect something to do with async, i.e. the image pixels aren't ready at the time the preview is assembled, because the preview does usually work if I cancel and start again.
This is with .NET10, WinUI 3 2.0
### Why is this important?
Print preview does not work properly - a user will be confused by blank areas where images should be.
### Steps to reproduce the bug
The full code is on [GitHub](https://github.com/pedro-w/PrintDemo)
# Main window
Registering for print
https://github.com/pedro-w/PrintDemo/blob/474c9e919797f2503bc4ca0c1d82edf35572e938/MainWindow.xaml.cs#L46-L63
```c#
private void PrintRegistration(bool reg)
{
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
if (hWnd == IntPtr.Zero) { return; }
PrintManager printManager = PrintManagerInterop.GetForWindow(hWnd);
if (reg)
{
// Register actions
printManager.PrintTaskRequested += PrintManager_PrintTaskRequested;
layout = new PrintLayout();
}
else
{
// Unregister actions
printManager.PrintTaskRequested -= PrintManager_PrintTaskRequested;
layout = null;
}
}
```
Print button handler
https://github.com/pedro-w/PrintDemo/blob/474c9e919797f2503bc4ca0c1d82edf35572e938/MainWindow.xaml.cs#L20-L45
```c#
private void PrintManager_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args)
{
if (layout != null)
{
IPrintDocumentSource documentSource = layout.DocumentSource;
args.Request.CreatePrintTask("Printing Demo", (task) => { task.SetSource(documentSource); });
}
}
```
# Print layout
https://github.com/pedro-w/PrintDemo/blob/474c9e919797f2503bc4ca0c1d82edf35572e938/PrintLayout.cs
```c#
internal class PrintLayout
{
internal PrintLayout()
{
printDocument = new PrintDocument();
printDocument.AddPages += AddPages;
printDocument.GetPreviewPage += GetPreviewPage;
printDocument.Paginate += Paginate;
documentSource = printDocument.DocumentSource;
}
private static Canvas MakeCanvas(PrintPageDescription pageDescription, UIElement content)
{
double marginLeftRight = DIP * 1.0;
double marginTopBottom = DIP * 1.0;
// Canvas covers the whole page
Canvas page0 = new() { Width = pageDescription.PageSize.Width, Height = pageDescription.PageSize.Height };
// Resize and position the content to respect the margins and the ImageableRect
double left = Math.Max(marginLeftRight, pageDescription.ImageableRect.Left);
double right = Math.Min(pageDescription.PageSize.Width - marginLeftRight, pageDescription.ImageableRect.Right);
double top = Math.Max(marginTopBottom, pageDescription.ImageableRect.Top);
double bottom = Math.Min(pageDescription.PageSize.Height - marginTopBottom, pageDescription.ImageableRect.Bottom);
page0.Children.Add(content);
// Set the size if we can
if (content is FrameworkElement el)
{
el.Width = right - left;
el.Height = bottom - top;
}
Canvas.SetLeft(content, left);
Canvas.SetTop(content, top);
return page0;
}
private static Canvas MakeFrontPage(PrintPageDescription pageDescription)
{
FrontPage fp = new();
Canvas page = MakeCanvas(pageDescription, fp);
return page;
}
private static Canvas MakeImagePage(int pagen, PrintPageDescription pageDescription)
{
ImagePage ip = new($"Page {pagen}");
Canvas page = MakeCanvas(pageDescription, ip);
return page;
}
private void Paginate(object sender, PaginateEventArgs e)
{
if (sender is PrintDocument document)
{
PrintTaskOptions options = e.PrintTaskOptions;
PrintPageDescription pageDescription = options.GetPageDescription(0);
printPreviewPages.Clear();
// Add a front page
Canvas page1 = MakeFrontPage(pageDescription);
printPreviewPages.Add(page1);
// And four image pages
for (int i = 2; i <= 5; ++i)
{
Canvas pageN = MakeImagePage(i, pageDescription);
printPreviewPages.Add(pageN);
}
document.SetPreviewPageCount(printPreviewPages.Count, PreviewPageCountType.Final);
}
}
private void GetPreviewPage(object sender, GetPreviewPageEventArgs e)
{
if (sender is PrintDocument document)
{
UIElement el = printPreviewPages[e.PageNumber - 1];
document.SetPreviewPage(e.PageNumber, el);
}
}
private void AddPages(object sender, AddPagesEventArgs e)
{
if (sender is PrintDocument document)
{
foreach (UIElement elem in printPreviewPages)
{
document.AddPage(elem);
}
document.AddPagesComplete();
}
}
private const double DIP = 96.0; // conversion factor from Device Independent Pixels to inch.
private readonly PrintDocument printDocument;
private readonly IPrintDocumentSource documentSource;
public IPrintDocumentSource DocumentSource { get => documentSource; }
private readonly List printPreviewPages = [];
}
```
# Image page to be printed
```xml
```
### Actual behavior
What happens is the first page with no images is OK, second page has no images, third and subsequent pages are OK
I'm not seeing any errors in the debug log.
### Expected behavior
Each image preview page should have 6 images in it (see screenshot)
### Screenshots
### NuGet package version
Microsoft.WindowsAppSDK 2.0.1
### Windows version
Windows 11 (24H2): Build 26100
### Additional context
_No response_
Contributor guide
Research direction
Start by reproducing the issue with the linked PrintDemo sample, then read MainWindow.xaml.cs, PrintLayout.cs, and ImagePage.xaml, focusing on the PrintDocument pagination, preview, and page-add callbacks. Confirm the behavior across the first several pages and compare it with the expected result of six visible images on every image page.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100