WPF中DocumentViewer能否显示图片?求实现方案
WPF DocumentViewer显示XPS图片问题解决
核心结论
DocumentViewer完全支持显示XPS文档中的图片,你的测试代码失效的原因是图片未被正确嵌入XPS包,仅保留了本地路径引用,导致加载XPS时无法读取图片资源。
问题根源
你在FlowDocument中使用了图片的绝对本地路径,默认情况下将FlowDocument序列化为XPS时,不会自动将外部图片文件嵌入到XPS包内,XPS文档仅记录了路径。当DocumentViewer打开XPS时,要么找不到对应路径的图片,要么因权限问题无法访问,最终导致图片不显示。
修复方案
方案1:将图片作为项目资源嵌入(推荐)
- 将图片文件添加到WPF项目中,右键图片→属性,设置生成操作为
Resource。 - 修改XAML中的Image Source为资源路径:
<Image Source="pack://application:,,,/33.jpg" Width="200" Height="200" />
这种方式下,序列化XPS时图片会自动嵌入到包内,DocumentViewer可以直接读取显示。
方案2:手动处理外部动态图片
如果图片是外部加载的(比如用户选择的本地图片),需要在序列化前将图片加载到内存并设置缓存模式,确保能被XPS序列化器捕获:
var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.UriSource = new Uri(@"C:\Users\Admin\Downloads\XpsTest-main\XpsTest-main\33.jpg"); bitmap.CacheOption = BitmapCacheOption.OnLoad; // 必须:加载后缓存到内存,避免序列化时丢失 bitmap.EndInit(); // 替换FlowDocument中的图片源 var image = flowDocument.FindName("targetImage") as Image; if (image != null) image.Source = bitmap;
完整可运行代码示例
修改后的XAML
<StackPanel Orientation="Horizontal" > <FlowDocumentReader Height="150" Width="170"> <FlowDocument Name="flowDocument" ColumnWidth="400" FontSize="14" FontFamily="Georgia"> <Paragraph> <Grid> <Image Name="targetImage" Source="pack://application:,,,/33.jpg" Width="200" Height="200" /> <TextBlock Text="Hello World!" HorizontalAlignment="Center" VerticalAlignment="Top" Foreground="Red" /> </Grid> </Paragraph> </FlowDocument> </FlowDocumentReader> <StackPanel> <Button Click="Button_Click" Content="save"/> <Button Click="Button_Click_1" Content="show"/> </StackPanel> <DocumentViewer Name="viewer" Width="600"/> </StackPanel>
修改后的C#代码
using System.IO; using System.IO.Packaging; using System.Windows; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Xps; using System.Windows.Xps.Packaging; using System.Windows.Xps.Serialization; namespace XpsTest { public partial class MainWindow : Window { private XpsDocument _xpsDocument; // 保存引用避免被GC回收 public MainWindow() => InitializeComponent(); public static void SaveAsXps(string path, FlowDocument document) { using (var package = Package.Open(path, FileMode.Create)) using (var xpsDoc = new XpsDocument(package, CompressionOption.Maximum)) { var serializationManager = new XpsSerializationManager(new XpsPackagingPolicy(xpsDoc), false); serializationManager.SaveAsXaml(((IDocumentPaginatorSource)document).DocumentPaginator); } } private void Button_Click(object sender, RoutedEventArgs e) { // 加载外部图片并设置缓存(若使用项目资源可跳过此段) var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.UriSource = new Uri(@"C:\Users\Admin\Downloads\XpsTest-main\XpsTest-main\33.jpg"); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.EndInit(); targetImage.Source = bitmap; SaveAsXps(@"C:\Users\Admin\Desktop\temp.xps", flowDocument); } private void Button_Click_1(object sender, RoutedEventArgs e) { _xpsDocument = new XpsDocument(@"C:\Users\Admin\Desktop\temp.xps", FileAccess.Read); viewer.Document = _xpsDocument.GetFixedDocumentSequence(); } } }
关键注意点
- 必须保留
XpsDocument实例的引用:如果在方法内局部声明XpsDocument,会被GC回收,导致DocumentViewer无法加载XPS内容,需将其声明为窗口级变量。 - 外部图片需确保程序有读取权限:若图片在受保护路径(如C盘根目录),需以管理员权限运行程序。
内容的提问来源于stack exchange,提问作者wpf
相关产品推荐
相关产品推荐

