我在获取FlowDocument中包含的图像时遇到一些困难,以显示FlowDocument何时保存为XPS文档。
以下是我的工作:
如果我在XPS查看器中查看保存的文件,则不会显示图像。问题是,在WPF实际显示在屏幕上之前不会加载图像,因此它们不会保存到XPS文件中。因此,有一种解决方法:如果我首先使用FlowDocumentPageViewer在屏幕上显示文档,然后保存XPS文件,则会加载图像并显示在XPS文件中。即使隐藏了FlowDocumentPageViewer,这也可以工作。但这给了我另一个挑战。这是我想做的(伪代码):
void SaveDocument()
{
AddFlowDocumentToFlowDocumentPageViewer();
SaveFlowDocumentToXpsFile();
}
这当然不起作用,因为在文档保存到XPS文件之前,FlowDocumentPageViewer永远不会有机会显示其内容。我尝试在调用Dispatcher.BeginInvoke时包装SaveFlowDocumentToXpsFile但它没有帮助。
我的问题是:
答案 0 :(得分:1)
情侣...... 你确定图像在写入之前是大小的吗?通常你必须在控件上调用Measure,以便它可以相应地调整自身的大小(无穷大让控件扩展到它的宽度和高度)
image.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
此外,有时您必须碰撞UI线程,以便在控件中更新所有内容
Dispatcher.Invoke(DispatcherPriority.Render, new Action(() =>{}));
答案 1 :(得分:0)
最终的解决方案与您的解决方案相同,即将文档放入查看器并在屏幕上简要显示。下面是我为此编写的帮助方法。
private static string ForceRenderFlowDocumentXaml =
@"<Window xmlns=""http://schemas.microsoft.com/netfx/2007/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<FlowDocumentScrollViewer Name=""viewer""/>
</Window>";
public static void ForceRenderFlowDocument(FlowDocument document)
{
using (var reader = new XmlTextReader(new StringReader(ForceRenderFlowDocumentXaml)))
{
Window window = XamlReader.Load(reader) as Window;
FlowDocumentScrollViewer viewer = LogicalTreeHelper.FindLogicalNode(window, "viewer") as FlowDocumentScrollViewer;
viewer.Document = document;
// Show the window way off-screen
window.WindowStartupLocation = WindowStartupLocation.Manual;
window.Top = Int32.MaxValue;
window.Left = Int32.MaxValue;
window.ShowInTaskbar = false;
window.Show();
// Ensure that dispatcher has done the layout and render passes
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Loaded, new Action(() => {}));
viewer.Document = null;
window.Close();
}
}
修改:我刚刚将window.ShowInTaskbar = false
添加到方法中,就好像您很快就可以看到窗口出现在任务栏中。
用户永远不会“看到”窗口,因为它位于Int32.MaxValue
的屏幕外 - 这是早期多媒体创作时常见的技巧(例如Macromedia / Adobe Director)。
对于搜索和查找此问题的人,我可以告诉您没有其他方式强制文档呈现。
HTH,
答案 2 :(得分:0)
您无需显示文档即可将图像保存到xps中。你在XpsSerializationManager上调用commit吗?
FlowDocument fd = new FlowDocument();
fd.Blocks.Add(new Paragraph(new Run("This is a test")));
string image = @"STRING_PATH";
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(image, UriKind.RelativeOrAbsolute);
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
MemoryStream ms = new MemoryStream();
Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
Uri pkgUri = bi.UriSource;
PackageStore.AddPackage(pkgUri, pkg);
Image img = new Image();
img.Source = bi;
BlockUIContainer blkContainer = new BlockUIContainer(img);
fd.Blocks.Add(blkContainer);
DocumentPaginator paginator = ((IDocumentPaginatorSource)fd).DocumentPaginator;
using (XpsDocument xps = new XpsDocument(@"STRING PATH WHERE TO SAVE FILE", FileAccess.ReadWrite, CompressionOption.Maximum))
{
using (XpsSerializationManager serializer = new XpsSerializationManager(new XpsPackagingPolicy(xps), false))
{
serializer.SaveAsXaml(paginator);
serializer.Commit();
}
}
答案 3 :(得分:0)
我能够通过将流文档扔到查看器中来解决此问题,然后进行度量/安排。
FlowDocumentScrollViewer flowDocumentScrollViewer = new FlowDocumentScrollViewer();
flowDocumentScrollViewer.Document = flowDocument;
flowDocumentScrollViewer.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
flowDocumentScrollViewer.Arrange(new Rect(new Point(0, 0), new Point(Double.MaxValue, Double.MaxValue)));