如何让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();
}发布于 2011-02-25 04:10:34
我讨厌回答我自己的问题,但是,下面给了我一个合理的解决方案: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();
}
}发布于 2020-02-11 15:31:12
对于那些对不同的、也许更“高级”的解决方案感兴趣的人,请继续查看XAML on GitHub,在那里我演示了如何创建my repository报表、对报表进行分页,然后从报表生成可打印的FixedDocument。
魔术发生在Paginator.cs中,代码遍历所有自定义附加属性,并使用它们来确定在哪里设置页码,哪些元素仅在第一页显示,等等……
所有报表都定义为普通的XAML用户控件,并在完成分页后转换为固定页。好处是您可以用纯XAML定义文档/报告,添加一些附加属性,然后分页器代码就可以完成剩下的工作。
发布于 2020-08-15 18:40:53
这个问题已经有很长一段时间没有回答了。
我尝试了Doo Dah的答案,但问题是它不会处理流文档的页面填充。
因此,我写了自己的解决方案(Doo Dah的答案帮助我完成了它):
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;
}您必须为之前将要显示的内容构建一个FlowDocument,并将其传递给该方法。
添加了PrintDialog变量以从我的预览窗口调用该方法,并可以传递当前打印机设置。
如果您从主程序调用它,您可以传递new PrintDialog()或null,这没有区别,因为如果您传递null,它将创建一个new PrintDialog
对于不同类型的文本(标题、文本、字体)的Flowdocument,这对我来说工作得很好。
它应该适用于图片和文本混合,或者只使用图片-它使用的是视觉效果,而不是来自流程文档的特定内容,因此它也应该适用于分页。
我没有尝试Shahin Dohan的答案,因为这是经常出现的问题。
它是在MVVM上编写的,当其他人编写它时,它很难理解。
在我看来,写一个没有mvvm的小示例程序会更好,人们可以熟练地使用mvvm,或者只使用代码。
我理解mvvm的机会,但要向某人展示如何工作,我看到的只是缺点(如果你不展示特定的mvvm技师)
https://stackoverflow.com/questions/5107880
复制相似问题