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

如何等待异步加载的图片完成后再添加到FixedDocument打印?

问题描述

在WPF中打印FixedDocument时,绑定的图片区域为空,原因是图片异步加载完成前视图已被添加到文档中。相关代码如下:

后台代码

MyView myView = new MyView();
MyView.DataContext = datacontext;

FixedPage fixedPage = new FixedPage();
fixedPage.Children.Add(myView);

PageContent pageContent = new PageContent();
((IAddChild)pageContent).AddChild(fixedPage);

FixedDocument fixedDocument = new FixedDocument();
fixedDocument.Pages.Add(pageContent);

PrintDialog printDialog = new PrintDialog();
printDialog.PrintDocument(fixedDocument.DocumentPaginator, "test");

MyView的XAML代码

<Image Source="{Binding ImagePath, Mode=OneWay, IsAsync=True}" />

需求:除设置IsAsync=False外,确保图片加载完成后再执行打印。


解决方案

方法1:监听Image的Loaded事件触发打印

通过视觉树查找MyView中的Image控件,监听其Loaded事件,确认图片加载完成后再执行打印逻辑。如果图片已通过本地缓存加载完成,则直接触发打印。

MyView myView = new MyView();
myView.DataContext = datacontext;

Image imageControl = FindVisualChild<Image>(myView);
bool isImageLoaded = false;

if (imageControl != null)
{
    imageControl.Loaded += (s, e) =>
    {
        ExecutePrint(myView);
    };
}

// 图片已加载完成的情况(如本地缓存)
if (imageControl != null && imageControl.IsLoaded)
{
    ExecutePrint(myView);
}

// 视觉树查找子控件的通用方法
private T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(parent, i);
        if (child is T target)
        {
            return target;
        }
        var childOfChild = FindVisualChild<T>(child);
        if (childOfChild != null)
            return childOfChild;
    }
    return null;
}

// 提取打印逻辑到独立方法
private void ExecutePrint(MyView myView)
{
    FixedPage fixedPage = new FixedPage();
    fixedPage.Children.Add(myView);

    PageContent pageContent = new PageContent();
    ((IAddChild)pageContent).AddChild(fixedPage);

    FixedDocument fixedDocument = new FixedDocument();
    fixedDocument.Pages.Add(pageContent);

    PrintDialog printDialog = new PrintDialog();
    printDialog.PrintDocument(fixedDocument.DocumentPaginator, "test");
}

方法2:手动加载图片后再绑定

不依赖Image的异步加载,在后台手动加载图片,确认加载完成后再赋值给绑定属性,随后执行打印。

// 手动加载图片
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(datacontext.ImagePath);
bitmap.EndInit();

// 根据图片加载状态处理
if (!bitmap.IsDownloading)
{
    datacontext.ImageSource = bitmap;
    ExecutePrint();
}
else
{
    bitmap.DownloadCompleted += (s, e) =>
    {
        datacontext.ImageSource = bitmap;
        ExecutePrint();
    };
}

// 对应修改MyView的XAML绑定
<!-- MyView中Image的绑定改为同步 -->
<Image Source="{Binding ImageSource, Mode=OneWay}" />

方法3:利用Dispatcher等待视图渲染完成

将视图临时添加到不可见容器,强制完成布局测量与排列,再通过Dispatcher以Render优先级等待渲染完成后执行打印。

MyView myView = new MyView();
myView.DataContext = datacontext;

// 临时容器触发视图布局
Grid tempGrid = new Grid();
tempGrid.Children.Add(myView);
myView.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
myView.Arrange(new Rect(myView.DesiredSize));

// 等待渲染完成后打印
Application.Current.Dispatcher.InvokeAsync(() =>
{
    ExecutePrint(myView);
}, DispatcherPriority.Render);

内容的提问来源于stack exchange,提问作者Anas Ansary

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 21:35:12