WinUI 3应用打印预览与输出图片缺失问题求助
WinUI 3 打印前几页图片缺失问题解决
问题根因
本地Assets图片异步加载时,打印预览/输出的页面生成逻辑未等待图片像素完全就绪,导致前1-2页图片未渲染就被提交到打印队列。取消后重开预览时图片已缓存,因此能正常显示。
解决方案
1. 预加载所有打印图片并等待就绪
提前批量加载所有需要打印的图片,确保每个图片的像素数据完全加载后再处理打印分页。可以用TaskCompletionSource包装BitmapImage的加载过程:
private async Task<List<BitmapImage>> PreloadPrintImages(List<string> assetPaths) { var images = new List<BitmapImage>(); foreach (var path in assetPaths) { var tcs = new TaskCompletionSource<bool>(); var bitmap = new BitmapImage(); bitmap.ImageOpened += (s, e) => tcs.TrySetResult(true); bitmap.ImageFailed += (s, e) => tcs.TrySetException(e.ErrorException); var uri = new Uri($"ms-appx:///Assets/{path}"); await bitmap.SetSourceAsync(await StorageFile.GetFileFromApplicationUriAsync(uri) .OpenAsync(FileAccessMode.Read)); await tcs.Task; // 等待图片完全加载 images.Add(bitmap); } return images; }
在打印初始化时先调用这个方法预加载,再将加载好的图片传入打印页面生成逻辑。
2. 修改打印分页与预览逻辑
在PrintDocument.Paginate事件中,确保已拿到所有预加载完成的图片后再计算页数,避免异步加载拖慢页面生成:
private List<BitmapImage> _preloadedImages; private async void PrintDocument_Paginate(object sender, PaginateEventArgs e) { // 预加载所有需要打印的图片(仅首次打印时执行,避免重复加载) if (_preloadedImages == null) { var assetPaths = new List<string> { "img1.png", "img2.png", "img3.png" }; // 替换为你的图片路径 _preloadedImages = await PreloadPrintImages(assetPaths); } // 计算总页数 printDocument.SetPreviewPageCount(_preloadedImages.Count, PreviewPageCountType.Final); } private void PrintDocument_GetPreviewPage(object sender, GetPreviewPageEventArgs e) { // 直接使用预加载完成的图片创建打印页面 var page = new PrintPage(); // 你的打印页面UserControl page.PrintImage.Source = _preloadedImages[e.PageNumber - 1]; printDocument.SetPreviewPage(e.PageNumber, page); }
3. 优化本地图片加载方式(针对Assets文件)
对于本地Assets中的图片,可使用同步流加载减少异步延迟,确保图片数据立即就绪:
private BitmapImage LoadAssetImageSync(string assetPath) { var uri = new Uri($"ms-appx:///Assets/{assetPath}"); var file = StorageFile.GetFileFromApplicationUriAsync(uri).AsTask().Result; using var stream = file.OpenAsync(FileAccessMode.Read).AsTask().Result; var bitmap = new BitmapImage(); bitmap.SetSource(stream); return bitmap; }
注意:仅本地Assets文件适合用同步加载,避免阻塞UI线程,建议在后台线程执行预加载后再回到UI线程处理打印。
4. 禁用图片延迟加载
在BitmapImage创建时设置CreateOptions为None,避免默认的延迟加载行为:
var bitmap = new BitmapImage(); bitmap.CreateOptions = BitmapCreateOptions.None;
内容的提问来源于stack exchange,提问作者Peter Hull
相关产品推荐
相关产品推荐

