You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 23:47:26