如何等待异步加载的图片完成后再添加到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
相关产品推荐
相关产品推荐

