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

WPF中DocumentViewer能否显示图片?求实现方案

WPF DocumentViewer显示XPS图片问题解决

核心结论

DocumentViewer完全支持显示XPS文档中的图片,你的测试代码失效的原因是图片未被正确嵌入XPS包,仅保留了本地路径引用,导致加载XPS时无法读取图片资源。

问题根源

你在FlowDocument中使用了图片的绝对本地路径,默认情况下将FlowDocument序列化为XPS时,不会自动将外部图片文件嵌入到XPS包内,XPS文档仅记录了路径。当DocumentViewer打开XPS时,要么找不到对应路径的图片,要么因权限问题无法访问,最终导致图片不显示。

修复方案

方案1:将图片作为项目资源嵌入(推荐)

  1. 将图片文件添加到WPF项目中,右键图片→属性,设置生成操作为Resource。
  2. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 03:45:46