Definir en qué parte de la página el documento de flujo que estoy imprimiendo 'comenzará' y 'finalizará'

Casi he terminado de implementar una funcionalidad de impresión, pero tengo problemas para resolver el último obstáculo.

Mi problema es que estoy imprimiendo algunos informes, que consisten en un encabezado (con información sobre la persona de la que trata el informe), un pie de página (con un número de página) y el contenido en el medio, que es un FlowDocument. Dado que los documentos de flujo pueden ser bastante largos, es muy posible que abarquen varias páginas.

Mi enfoque es hacer un FlowDocumentPaginator personalizado que se deriva de DocumentPaginator.

Ahí defino mi encabezado y mi pie de página.

Sin embargo, cuando imprimo mi página, el documento de flujo y mi encabezado y pie de página están uno encima del otro.

Entonces, mi pregunta es simple y simple: ¿cómo defino desde dónde y dónde se colocará la parte del documento de flujo en las páginas?

Aquí está el código de mi Paginator personalizado:

public class HeaderedFlowDocumentPaginator : DocumentPaginator
{
    private DocumentPaginator flowDocumentpaginator;

    public HeaderedFlowDocumentPaginator(FlowDocument document)
    {
        flowDocumentpaginator = ((IDocumentPaginatorSource) document).DocumentPaginator;
    }

    public override bool IsPageCountValid
    {
        get { return flowDocumentpaginator.IsPageCountValid; }
    }

    public override int PageCount
    {
        get { return flowDocumentpaginator.PageCount; }
    }

    public override Size PageSize
    {
        get { return flowDocumentpaginator.PageSize;  }
        set { flowDocumentpaginator.PageSize = value; }
    }

    public override IDocumentPaginatorSource Source
    {
        get { return flowDocumentpaginator.Source; }
    }

    public override DocumentPage GetPage(int pageNumber)
    {
        DocumentPage page = flowDocumentpaginator.GetPage(pageNumber);

        ContainerVisual newVisual = new ContainerVisual();
        newVisual.Children.Add(page.Visual);

        DrawingVisual header = new DrawingVisual();
        using (DrawingContext dc = header.RenderOpen())
        {
            //Header data
        }
        newVisual.Children.Add(header);

        DrawingVisual footer = new DrawingVisual();
        using (DrawingContext dc = footer.RenderOpen())
        {
            Typeface typeface = new Typeface("Trebuchet MS");
            FormattedText text = new FormattedText("Page " + (pageNumber + 1).ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 14, Brushes.Black);

            dc.DrawText(text, new Point(page.Size.Width - 100, page.Size.Height-30));
        }

        newVisual.Children.Add(footer);

        DocumentPage newPage = new DocumentPage(newVisual);
        return newPage;
    }
}

Y aquí está la llamada printdialogue:

private void btnPrint_Click(object sender, RoutedEventArgs e)
{
    try
    {
        PrintDialog printDialog = new PrintDialog();
        if (printDialog.ShowDialog() == true)
        {
            FlowDocument fd = new FlowDocument();
            MemoryStream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(<My string of text - RTF formatted>));

            TextRange tr = new TextRange(fd.ContentStart, fd.ContentEnd);
            tr.Load(stream, DataFormats.Rtf);

            stream.Close();
            fd.ColumnWidth = printDialog.PrintableAreaWidth;

            HeaderedFlowDocumentPaginator paginator = new HeaderedFlowDocumentPaginator(fd);

            printDialog.PrintDocument(paginator, "myReport");
        }
    }
    catch (Exception ex)
    {
        //Handle
    }
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta