Search code examples
wpfpaginationfixeddocument

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

Solution

  • 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();
        }
    }