Search code examples
wpfpaginationflowdocument

Dynamic printable content area


I am using WPF Flowdocument to print content in a Table with Header and Footer.

However, when the data occupies only couple of rows in the table, footer section still reflects at the last of the page and the whole page gets printed, leaving half of the page blank.

Can I expect the content (Header + Content + Footer) to occupy only half of the page if the data is less and one full page (A4/Letter page) if the data is more than half page? And if the data is more than a full page, it should span to the second page too.


Solution

  • I am able to solve this by overriding OnPrintCommand for DocumentViewer

    public class CustomDocumentViewer : DocumentViewer
    {
        protected override void OnPrintCommand()
        {
            // get a print dialog, defaulted to default printer and default printer's preferences.
            PrintDialog printDialog = new PrintDialog();
            printDialog.PrintQueue = LocalPrintServer.GetDefaultPrintQueue();
            printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket;
    
            // get a reference to the FixedDocumentSequence for the viewer.
            FixedDocumentSequence docSeq = this.Document as FixedDocumentSequence;
    
            if (Globals.PRINT_COMMAND_PAGEHEIGHT == "FULL")
                printDialog.PrintTicket.PageMediaSize = new PageMediaSize(960, 1152);
            else
                printDialog.PrintTicket.PageMediaSize = new PageMediaSize(960, 576);
    
            if (printDialog.ShowDialog() == true)
            {
                // set the print ticket for the document sequence and write it to the printer.
                docSeq.PrintTicket = printDialog.PrintTicket;
    
                XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printDialog.PrintQueue);
                writer.WriteAsync(docSeq, printDialog.PrintTicket);
            }
        }
    }
    

    Window_Activated function:

                //Set Page Height and Width dynamically
    
                MemoryStream mem = new MemoryStream();
                byte[] buf = Encoding.UTF8.GetBytes(strXmlData);
                mem.Write(buf, 0, buf.Length);
                mem.Position = 0;
                FlowDocument res = XamlReader.Load(mem) as FlowDocument;
    
                //1152 = 12in * 96 DPI
    
                if (Utils.GetPageHeight(strOrderNo.Substring(0, 2)) == "FULL")
                {
                    res.PageHeight = Globals.FULL_PAGE_HEIGHT;
                    Globals.PRINT_COMMAND_PAGEHEIGHT = "FULL";
                }
                else
                {
                    res.PageHeight = Globals.HALF_PAGE_HEIGHT;
                    Globals.PRINT_COMMAND_PAGEHEIGHT = "HALF";
                }
                res.PageWidth = Globals.PAGE_WIDTH;
    
                reportDocument.XamlData = XamlWriter.Save(res);
    

    in the DocumentViewer xaml file:

    <Grid>
        <spu:CustomDocumentViewer x:Name="documentViewer" />
    </Grid>
    

    and in the Flowdocument Template:

    PageHeight="0.0cm" PageWidth="0.0cm" ColumnWidth="21.0cm"
    

    Thanks, ~ Ravi