Печать BlockUIContainer в XpsDocument / FixedDocument

Вопрос

  1. Как распечатать FlowDocument, который имеет BlockUIContainer ?
  2. Как я могу принудительно включить Measure / Update / Arrange a FlowDocument?

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;
} 

9
задан Community 23 May 2017 в 12:16
поделиться