WPF固定文档分页

WPF固定文档分页,wpf,pagination,fixeddocument,Wpf,Pagination,Fixeddocument,如何使FixedDocument自动分页?我有下面的代码,我可以用它把经过修饰的面板放到DocViewer中。当面板延伸超过单个页面时,就会出现问题。现在,我们只是简单地剪辑。基本上,我想创建一种相当通用的方式来打印用户正在查看的内容。我的方法合理吗 public void CreateReport(Panel details) { FixedDocument fixedDoc = new FixedDocument(); PageContent

如何使FixedDocument自动分页?我有下面的代码,我可以用它把经过修饰的面板放到DocViewer中。当面板延伸超过单个页面时,就会出现问题。现在,我们只是简单地剪辑。基本上,我想创建一种相当通用的方式来打印用户正在查看的内容。我的方法合理吗

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

我讨厌回答我自己的问题,但是,下面给了我一个合理的解决方案:

斯科特

公共静态类PrintHelper
{
公共静态固定文档GetFixedDocument(框架元素toPrint,PrintDialog PrintDialog)
{
PrintCapabilities=printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);
大小pageSize=新大小(printDialog.PrintableAreaWidth、printDialog.PrintableAreaHeight);
大小visibleSize=新大小(capabilities.PageImageableArea.extendWidth,capabilities.PageImageableArea.extendWidth);
FixedDocument fixedDoc=新的FixedDocument();
//如果屏幕上没有显示toPrint visual,我们需要对其进行测量和排列。
toPrint.Measure(新尺寸(双精度正精度,双精度正精度));
toPrint.Arrange(新矩形(新点(0,0),toPrint.DesiredSize));
尺寸=TopPrint.DesiredSize;
//为简单起见,将假定控件水平放置在页面上。
双yOffset=0;
而(yOffset<尺寸高度)
{
VisualBrush vb=新的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=新的PageContent();
FixedPage=新的FixedPage();
((IAddChild)页面内容).AddChild(页面);
fixedDoc.Pages.Add(页面内容);
page.Width=pageSize.Width;
page.Height=pageSize.Height;
画布=新画布();
FixedPage.SetLeft(canvas,capabilities.PageImageableArea.OriginWidth);
FixedPage.SetTop(画布、功能、PageImageableArea.OriginHeight);
canvas.Width=visibleSize.Width;
canvas.Height=visibleSize.Height;
canvas.Background=vb;
page.Children.Add(画布);
yOffset+=可见大小。高度;
}
返回固定DOC;
}
公共静态无效显示打印预览(FixedDocument fixedDoc)
{
窗口wnd=新窗口();
DocumentViewer=新建DocumentViewer();
viewer.Document=fixedDoc;
wnd.Content=viewer;
wnd.ShowDialog();
}
}

对于那些对另一种可能更“高级”的解决方案感兴趣的人,请访问GitHub,在那里我演示了如何创建XAML报告,对其分页,然后从中生成可打印的固定文档

神奇发生在Paginator.cs中,代码遍历所有自定义附加属性,并使用它们确定在何处设置页码,哪些元素仅显示在第一页,等等


所有报告都定义为普通XAML用户控件,并在分页完成后转换为固定页面。这样做的好处是,您可以用纯XAML定义文档/报表,添加一些附加属性,分页器代码会处理其余的内容。

这个问题已经很久没有得到回答了。
我尝试了Doo Dah的答案,但问题是它不能处理flowdocument的页面填充

因此,我写了自己的解决方案(斗大的回答帮助我完成了它):

public Fixed document从\u FlowDoc获取\u Fixed\u(FlowDocument FlowDoc,PrintDialog printDlg)
{
var fixedDocument=新的fixedDocument();
尝试
{
pdlgPrint=printDlg??新建打印对话框();
DocumentPaginator dpPages=(DocumentPaginator)((IDocumentPaginatorSource)flowDoc)。DocumentPaginator;
dpPages.ComputePageCount();
PrintCapabilities=pdlgPrint.PrintQueue.GetPrintCapabilities(pdlgPrint.PrintTicket);
对于(int-iPages=0;iPages
您必须为之前显示的内容构建一个流程文档并传递它 到方法。
添加了PrintDialog变量以从我的预览窗口调用该方法,并可以传递当前打印机设置。

如果从主程序调用它,可以传递一个
newprintDialog()
null
,没有dif
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();
    }
}
public FixedDocument Get_Fixed_From_FlowDoc(FlowDocument flowDoc, PrintDialog printDlg)
{
    var fixedDocument = new FixedDocument();
    try
    {
        pdlgPrint = printDlg ?? 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;
}