【发布时间】:2012-03-15 21:10:32
【问题描述】:
问题
- 如何打印具有
BlockUIContainer的 FlowDocument? - 如何强制对 FlowDocument 进行测量/更新/排列?
背景
我生成了一个带有文本段落的 FlowDocument,其中包含一些来自资源字典的 DrawingBrushes 填充的 Rectangle 元素和带有自定义控件的 BlockUIContainer。
当文档被转换为 FixedDocument/XpsDocument 时,在任何 FlowDocument* 控件中查看时,文档都能正确呈现。但是,Rectangle 或 BlockUIContainer 元素都不会呈现。
我几乎可以肯定这是因为控件没有被测量/排列,但是在它被转换为 XpsDocument 之前无法弄清楚如何强制它发生。
-
我已经递归遍历
LogicalTree并完成了以下操作,UIElement element = (UIElement)d; element.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); element.Arrange(new Rect(element.DesiredSize)); element.UpdateLayout();其中
d是DependencyObject。我可以看到这会在调试器中设置断点时设置ActualWidth和ActualHeight属性。 我已尝试强制
Dispatcher按照 Will ♦ 的建议进行渲染。
用于打印 XpsDocument 的代码
public class XpsDocumentConverter
{
public static XpsDocumentReference CreateXpsDocument(FlowDocument document)
{
// Need to clone the document so that the paginator can work
FlowDocument clonedDocument = DocumentHelper.Clone<FlowDocument>(document);
Uri uri = new Uri(String.Format("pack://temp_{0}.xps/", Guid.NewGuid().ToString("N")));
MemoryStream ms = new MemoryStream();
Package pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
PackageStore.AddPackage(uri, pkg);
XpsDocument xpsDocument = new XpsDocument(pkg, CompressionOption.Normal, uri.AbsoluteUri);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(xpsDocument), false);
DocumentPaginator paginator = new FixedDocumentPaginator(clonedDocument, A4PageDefinition.Default);
rsm.SaveAsXaml(paginator);
return new XpsDocumentReference(ms, xpsDocument);
}
}
如您所见,我还使用了一个名为“FixedDocumentPaginator”的自定义DocumentPaginator;但是我不会发布该代码,因为我怀疑问题是否存在,因为当它开始在GetPage(int pageNumber) 中对文档进行分页时,所有内容都已转换为Visual,并且布局为时已晚。
编辑
嗯。在我输入此内容时,我突然想到克隆的文档 可能没有完成Measure/Arrange/UpdateLayout。
问题:如何强制对 FlowDocument 进行测量/更新/排列?
我可以工作的一个可能的技巧是在 FlowDocumentViewers 之一(可能在屏幕外)中显示克隆的文档。
我刚刚了解但尚未尝试的另一种可能的解决方案是致电:ContextLayoutManager.From(Dispatcher.CurrentDispatcher).UpdateLayout();
ContextLayoutManager 为您遍历逻辑树并更新布局。
用于克隆文档的代码
public static FlowDocument Clone(FlowDocument originalDocument)
{
FlowDocument clonedDocument = new FlowDocument();
TextRange sourceDocument = new TextRange(originalDocument.ContentStart, originalDocument.ContentEnd);
TextRange clonedDocumentRange = new TextRange(clonedDocument.ContentStart, clonedDocument.ContentEnd);
try
{
using (MemoryStream ms = new MemoryStream())
{
sourceDocument.Save(ms, DataFormats.XamlPackage);
clonedDocumentRange.Load(ms, DataFormats.XamlPackage);
}
clonedDocument.ColumnWidth = originalDocument.ColumnWidth;
clonedDocument.PageWidth = originalDocument.PageWidth;
clonedDocument.PageHeight = originalDocument.PageHeight;
clonedDocument.PagePadding = originalDocument.PagePadding;
clonedDocument.LineStackingStrategy = clonedDocument.LineStackingStrategy;
return clonedDocument;
}
catch (Exception)
{
}
return null;
}
【问题讨论】:
标签: c# wpf printing flowdocument xpsdocument