后台代码为BitmapImage分配StreamSource及Zip图片嵌入问题
解决FlowDocument图片导出XAML丢失StreamSource的问题
首先咱们得搞清楚问题根源:你当前用StreamSource加载的BitmapImage,虽然能正常显示,但**StreamSource是瞬态属性,XAML序列化时不会将它写入输出的XAML中**。只有UriSource这类持久化属性会被保留,这就是导出的XAML里BitmapImage为空的原因。
而你看到的复制粘贴后的正常XAML,本质是把图片数据以可持久化的方式关联到了BitmapImage上。要实现类似效果,我们可以把Zip里的图片转换成Base64格式的Data URI,赋值给BitmapImage的UriSource,这样导出XAML时就能完整保留图片信息,和复制粘贴的嵌入效果一致。
修改后的代码实现
替换你原来的图片加载逻辑部分,改成下面的代码:
foreach (var image in images) { var imageFileEntry = archive.GetEntry(image.Tag.ToString()); if (imageFileEntry == null) continue; // 增加防错处理 var bitmap = new BitmapImage(); using (Stream imageFileStream = imageFileEntry.Open()) { // 1. 将图片流转为字节数组 byte[] imageBytes; using (var memoryStream = new MemoryStream()) { imageFileStream.CopyTo(memoryStream); imageBytes = memoryStream.ToArray(); } // 2. 生成Base64格式的Data URI string fileExtension = Path.GetExtension(imageFileEntry.Name).TrimStart('.'); // 适配常见图片类型的MIME格式 string mimeType = fileExtension.Equals("jpg", StringComparison.OrdinalIgnoreCase) || fileExtension.Equals("jpeg", StringComparison.OrdinalIgnoreCase) ? "image/jpeg" : $"image/{fileExtension}"; string dataUri = $"data:{mimeType};base64,{Convert.ToBase64String(imageBytes)}"; // 3. 初始化BitmapImage并赋值UriSource bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.UriSource = new Uri(dataUri); bitmap.EndInit(); image.Source = bitmap; } }
为什么这样能解决问题?
- Data URI是一种将文件数据直接嵌入到URI的格式,它包含了图片的所有二进制数据,无需依赖外部文件。
- 把
UriSource设置为这个Data URI后,BitmapImage会从URI加载图片数据,且该URI会被XAML序列化器识别并写入导出的XAML中,效果和复制粘贴完全一致。 - 导出后的XAML里,
BitmapImage会带有完整的UriSource属性,示例如下:<Image Tag="Media/image0.png"> <Image.Source> <BitmapImage CacheOption="OnLoad" UriSource="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..."/> </Image.Source> </Image>
额外说明
如果你希望导出的XAML保留相对路径(而非内嵌Base64),需要在导出XAML的同时,把Zip里的图片提取到和XAML文件同一目录,然后设置BitmapImage的UriSource为相对路径并指定BaseUri。但这种方式需要处理文件导出同步,而内嵌Base64的方式更贴合你想要的“复制粘贴嵌入”效果,无需依赖外部资源文件。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

