Вопрос
BlockUIContainer
? Background
У меня есть сгенерированный FlowDocument
с абзацами текста с несколькими заполненными элементами Rectangle
DrawingBrushes
из словаря ресурсов и BlockUIContainer
с настраиваемыми элементами управления.
Документ отображается правильно при просмотре в любом из элементов управления FlowDocument * ОДНАКО , когда документ преобразован в FixedDocument / XpsDocument, ни один из Rectangle
или BlockUIContainer
рендеринг элементов.
Я почти уверен, что это потому, что элемент управления не был измерен / упорядочен , однако не могу понять, как заставить это происходить, прежде чем он будет преобразован в XpsDocument.
Я рекурсивно прошел по LogicalTree
и сделал следующее:
UIElement element = (UIElement) d;
element.Measure (новый размер (Double.PositiveInfinity, Double.PositiveInfinity));
element.Arrange (новый Rect (element.DesiredSize));
element.UpdateLayout ();
где d
- это DependencyObject
. Я вижу, что это устанавливает свойства ActualWidth
и ActualHeight
при установке точки останова в отладчике.
Я попытался заставить диспетчер
выполнять рендеринг, как было предложено Уиллом ♦ .
Код, используемый для печати 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(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);
}
}
Как видите, я также использую пользовательский DocumentPaginator
с именем 'FixedDocumentPaginator'; однако я не буду публиковать этот код, поскольку сомневаюсь, что проблема существует, поскольку к тому времени, когда он начинает разбивать документ на страницы в GetPage (int pageNumber)
, все уже было преобразовано в Visual
, и это слишком поздно для верстки.
Править
Хм. Когда я набирал это, мне пришла в голову мысль, что в клонированном документе , возможно, не было выполнено Measure / Arrange / UpdateLayout
.
Вопрос: Как я могу принудительно выполнить измерение / обновление / упорядочение в FlowDocument?
Возможный способ взлома, который я мог бы использовать, - это показать клонированный документ в одном из FlowDocumentViewer (возможно, за пределами экрана) .
Другое возможное решение, о котором я только что узнал и не пробовал, - это вызвать: 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;
}