Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF FixedDocument pagination

How do I get FixedDocument to automatically paginate? I have the following code that I can use to put prettified Panel into a DocViewer. The problem occurs when the Panel extends past a single page. Right now, we simply clip. Basically, I want to create a fairly generic way to print what the user is viewing. Is my approach reasonable?

    public void CreateReport(Panel details)
    {
        FixedDocument fixedDoc = new FixedDocument();
        PageContent pageContent = new PageContent();
        FixedPage fixedPage = new FixedPage();

        fixedPage.DataContext = this.DataContext;
        fixedPage.Margin = new Thickness(10);

        fixedPage.Children.Add(details);
        ((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
        fixedDoc.Pages.Add(pageContent);

        // This makes the array of controls invisibile, then climbs the details structure
        // and makes the controls within details appropriate for the DocumentViewwer (i.e. TextBoxes are
        // non-editable, no borders, no scroll bars, etc).
        prePrintPrepare(details, fixedPage, new FrameworkElement[] { controlToMakeInvisible });

        _dv = new DocViewer();
        _dv.documentViewer1.Document = fixedDoc;
        _dv.Show();
    }
like image 669
Doo Dah Avatar asked Feb 24 '11 16:02

Doo Dah


2 Answers

For those who are interested in a different and maybe more "advanced" solution, go ahead and check out my repository on GitHub where I demonstrate how to create XAML reports, paginate them, then produce a printable FixedDocument from them.

The magic happens in Paginator.cs where the code goes through all the custom attached properties and uses them to determine where to set page number, which elements to show only on first page, and more...

All reports are defined as plain XAML user controls, and are converted to fixed pages after pagination is done. The benefit is that you can define your document/report in pure XAML, add a few attached properties, and the paginator code takes care of the rest.

like image 100
Shahin Dohan Avatar answered Sep 18 '22 17:09

Shahin Dohan


I hate answering my own question, but, the following gave me a reasonable solution: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/bd89e0d2-73df-4b9b-9210-b8be83ff29d6/

Scott

public static class PrintHelper
{
    public static FixedDocument GetFixedDocument(FrameworkElement toPrint, PrintDialog printDialog)
    {
        PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
        Size pageSize = new Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight);
        Size visibleSize = new Size(capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);
        FixedDocument fixedDoc = new FixedDocument();

        // If the toPrint visual is not displayed on screen we neeed to measure and arrange it.
        toPrint.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        toPrint.Arrange(new Rect(new Point(0, 0), toPrint.DesiredSize));

        Size size = toPrint.DesiredSize;

        // Will assume for simplicity the control fits horizontally on the page.
        double yOffset = 0;
        while (yOffset < size.Height)
        {
            VisualBrush vb = new VisualBrush(toPrint);
            vb.Stretch = Stretch.None;
            vb.AlignmentX = AlignmentX.Left;
            vb.AlignmentY = AlignmentY.Top;
            vb.ViewboxUnits = BrushMappingMode.Absolute;
            vb.TileMode = TileMode.None;
            vb.Viewbox = new Rect(0, yOffset, visibleSize.Width, visibleSize.Height);

            PageContent pageContent = new PageContent();
            FixedPage page = new FixedPage();
            ((IAddChild)pageContent).AddChild(page);
            fixedDoc.Pages.Add(pageContent);
            page.Width = pageSize.Width;
            page.Height = pageSize.Height;

            Canvas canvas = new Canvas();
            FixedPage.SetLeft(canvas, capabilities.PageImageableArea.OriginWidth);
            FixedPage.SetTop(canvas, capabilities.PageImageableArea.OriginHeight);
            canvas.Width = visibleSize.Width;
            canvas.Height = visibleSize.Height;
            canvas.Background = vb;
            page.Children.Add(canvas);

            yOffset += visibleSize.Height;
        }
        return fixedDoc;
    }

    public static void ShowPrintPreview(FixedDocument fixedDoc)
    {
        Window wnd = new Window();
        DocumentViewer viewer = new DocumentViewer();
        viewer.Document = fixedDoc;
        wnd.Content = viewer;
        wnd.ShowDialog();
    }
}
like image 42
Doo Dah Avatar answered Sep 19 '22 17:09

Doo Dah