WPF FixedDocument分页

时间:2011-02-24 16:59:06

标签: wpf pagination fixeddocument

如何让FixedDocument自动分页?我有以下代码可用于将美化面板放入DocViewer。当Panel扩展到单个页面时会发生此问题。现在,我们只是剪辑。基本上,我想创建一种相当通用的方式来打印用户正在查看的内容。我的方法合理吗?

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

3 个答案:

答案 0 :(得分:4)

我讨厌回答我自己的问题,但是,以下给了我一个合理的解决方案: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/bd89e0d2-73df-4b9b-9210-b8be83ff29d6/

斯科特

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

答案 1 :(得分:1)

对于那些对另一种也许更高级的解决方案感兴趣的人,请继续在GitHub上查看my repository,在此我将演示如何创建XAML报告,对其进行分页,然后从中生成可打印的FixedDocument 。

魔术发生在 Paginator.cs 中,其中代码将遍历所有自定义附加属性,并使用它们来确定在何处设置页码,哪些元素仅显示在首页上等等。 ..

所有报告均定义为普通XAML用户控件,并在完成分页后转换为固定页面。好处是您可以在纯XAML中定义文档/报告,添加一些附加属性,然后分页器代码将处理其余部分。

答案 2 :(得分:1)

回答问题已有很长时间了。
我尝试了杜达(Doo Dah)的答案,但问题是它没有处理flowdocument的页面填充。

因此,我编写了自己的解决方案(Doo Dah的回答帮助我完成了该解决方案):

 public FixedDocument Get_Fixed_From_FlowDoc(FlowDocument flowDoc, PrintDialog printDlg)
{
           var fixedDocument = new FixedDocument();
            try
            {
                if (printDlg != null)
                {
                    pdlgPrint = printDlg;
                }

            if (pdlgPrint == null)
            {
                pdlgPrint = new PrintDialog();
            }

            DocumentPaginator dpPages = (DocumentPaginator)((IDocumentPaginatorSource)flowDoc).DocumentPaginator;
            dpPages.ComputePageCount();
            PrintCapabilities capabilities = pdlgPrint.PrintQueue.GetPrintCapabilities(pdlgPrint.PrintTicket);
           

            for (int iPages= 0; iPages < dpPages.PageCount; iPages++)
            {

                var page = dpPages.GetPage(iPages);
                var pageContent = new PageContent();
                var fixedPage = new FixedPage();


                Canvas canvas = new Canvas();

                VisualBrush vb = new VisualBrush(page.Visual);
                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, 0, capabilities.PageImageableArea.ExtentWidth, capabilities.PageImageableArea.ExtentHeight);


                FixedPage.SetLeft(canvas, 0);
                FixedPage.SetTop(canvas, 0);
                canvas.Width = capabilities.PageImageableArea.ExtentWidth;
                canvas.Height = capabilities.PageImageableArea.ExtentHeight;
                canvas.Background = vb;

                fixedPage.Children.Add(canvas);

                fixedPage.Width = pdlgPrint.PrintableAreaWidth;
                fixedPage.Height = pdlgPrint.PrintableAreaHeight;
                pageContent.Child = fixedPage;
                fixedDocument.Pages.Add(pageContent);
            }
            dv1.ShowPageBorders = true;

        }
        catch (Exception)
        {
            throw;
        }
        return fixedDocument;
    }

您必须构建一个FlowDocument,将之前显示的内容传递给它 方法。
添加了PrintDialog变量以从我的预览窗口调用方法,并可以传递当前的打印机设置。

如果从主程序调用它,则可以传递new PrintDialog()null,没有区别,因为如果传递new PrintDialog,它将创建一个null

这对使用带有不同类型的文本(标题,文本,字体)的Flowdocument来说对我来说很好。

它应该使用混合了图片和文字的图片,也可以只使用图片-使用视觉效果,而不是流程文档中的特定内容,因此它也应该使用分页符。

我没有尝试使用Shahin Dohan的答案,因为它经常遇到相同的问题。
它是用MVVM编写的,很难理解别人是何时写的。
在我看来,最好编写一个没有mvvm的小示例程序,人们可以将其熟练地应用于mvvm或仅使用代码。
我了解mvvm的机会,但向某人展示如何工作的方法,我只会看到缺点(如果您不会显示特定的mvvm机制)