C# 使用 DocumentPaginator 打印时如何打印预览?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/584551/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to Print Preview when using a DocumentPaginator to print?
提问by Ray
I'm using a class I've derived from DocumentPaginator (see below) to print simple (text only) reports from a WPF application. I've got it so that everything prints correctly, But how do I get it to do a print preview before printing?I have a feeling I need to use a DocumentViewer but I can't figure out how.
我正在使用从 DocumentPaginator 派生的类(见下文)从 WPF 应用程序打印简单(纯文本)报告。我已经有了它,所以一切都可以正确打印,但是如何在打印前进行打印预览?我有一种感觉,我需要使用 DocumentViewer,但我不知道如何使用。
Here's my Paginator Class:
这是我的分页器类:
public class RowPaginator : DocumentPaginator
{
private int rows;
private Size pageSize;
private int rowsPerPage;
public RowPaginator(int rows)
{
this.rows = rows;
}
public override DocumentPage GetPage(int pageNumber)
{
int currentRow = rowsPerPage * pageNumber;
int rowsToPrint = Math.Min(rowsPerPage, rows - (rowsPerPage * pageNumber - 1));
var page = new PageElementRenderer(pageNumber + 1, PageCount, currentRow, rowsToPrint)
{
Width = PageSize.Width,
Height = PageSize.Height
};
page.Measure(PageSize);
page.Arrange(new Rect(new Point(0, 0), PageSize));
return new DocumentPage(page);
}
public override bool IsPageCountValid { get { return true; } }
public override int PageCount { get { return (int)Math.Ceiling(this.rows / (double)this.rowsPerPage); } }
public override Size PageSize
{
get { return this.pageSize; }
set
{
this.pageSize = value;
this.rowsPerPage = PageElementRenderer.RowsPerPage(this.pageSize.Height);
if (rowsPerPage <= 0)
throw new InvalidOperationException("Page can't fit any rows!");
}
}
public override IDocumentPaginatorSource Source { get { return null; } }
}
The PageElementRenderer is just a simple UserControl that displays the data (at the moment just a list of rows).
PageElementRenderer 只是一个简单的 UserControl,用于显示数据(目前只是一个行列表)。
Here's how I use my Row Paginator
这是我如何使用我的 Row Paginator
PrintDialog dialog = new PrintDialog();
if (dialog.ShowDialog() == true)
{
var paginator = new RowPaginator(rowsToPrint) { PageSize = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight) };
dialog.PrintDocument(paginator, "Rows Document");
}
Sorry for the code dump, but I didn't want to miss something relevant.
抱歉代码转储,但我不想错过相关的东西。
采纳答案by Ray
So I got it working after reading Pro WPF in C# 2008(Page 726).
因此,在阅读了 C# 2008 中的 Pro WPF(第 726 页)后,我开始使用它。
Basically the DocumentViewer class needs an XPS file to present a print preview of it. So I do the following:
基本上 DocumentViewer 类需要一个 XPS 文件来显示它的打印预览。所以我执行以下操作:
PrintDialog dialog = new PrintDialog();
var paginator = new RowPaginator(rowsToPrint) { PageSize = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight) };
string tempFileName = System.IO.Path.GetTempFileName();
//GetTempFileName creates a file, the XpsDocument throws an exception if the file already
//exists, so delete it. Possible race condition if someone else calls GetTempFileName
File.Delete(tempFileName);
using (XpsDocument xpsDocument = new XpsDocument(tempFileName, FileAccess.ReadWrite))
{
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
writer.Write(paginator);
PrintPreview previewWindow = new PrintPreview
{
Owner = this,
Document = xpsDocument.GetFixedDocumentSequence()
};
previewWindow.ShowDialog();
}
I'm creating the print dialog to get the default page size. There's probably a better way to do this. XpsDocument is in ReachFramework.dll (Namespace System.Windows.Xps.Packaging);
我正在创建打印对话框以获取默认页面大小。可能有更好的方法来做到这一点。XpsDocument 位于 ReachFramework.dll(命名空间 System.Windows.Xps.Packaging)中;
Here's the PrintPreview Window.
这是 PrintPreview 窗口。
<Window x:Class="WPFPrintTest.PrintPreview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="previewWindow"
Title="PrintPreview" Height="800" Width="800">
<Grid>
<DocumentViewer Name="viewer"
Document="{Binding ElementName=previewWindow, Path=Document}" />
</Grid>
</Window>
The code behind just has a Document property like so:
后面的代码只有一个 Document 属性,如下所示:
public IDocumentPaginatorSource Document
{
get { return viewer.Document; }
set { viewer.Document = value; }
}
回答by MrValdez
The WinForm code for print preview is:
打印预览的 WinForm 代码是:
PrintPreviewDialog PrintPreviewDialog = new PrintPreviewDialog();
PrintPreviewDialog.Document = PrintDocument;
PrintPreviewDialog.ShowDialog();
P.s.: The original poster has commented that this is the wrong answer for an WPF application.
Ps:原发帖人评论说这是WPF应用程序的错误答案。
回答by Simon
I dont think there is a built in way of doing this
我不认为有一种内置的方式来做到这一点
Here is how I got it working in NHaml
这是我在 NHaml 中工作的方式
var documentViewHostDialog = new DocumentDialog();
documentViewHostDialog.LoadDocument(load);
documentViewHostDialog.ShowDialog();
Where "load" is either a FlowDocument or IDocumentPaginatorSource and here is the DocumentDialog http://code.google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xamlhttp://code.google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml.cs
其中“加载”是 FlowDocument 或 IDocumentPaginatorSource,这里是 DocumentDialog http://code.google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml http://code。 google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml.cs
Hope it works for your case.
希望它适用于您的情况。
回答by Fortes
WPF doesn't come with any built-in Print Preview functionality, if you want to do a print preview, you're going to have to construct it yourself. Fortunately, it's shouldn't be that difficult.
WPF 没有任何内置的打印预览功能,如果你想进行打印预览,你将不得不自己构建它。幸运的是,这应该不是那么困难。
You've already got the pagination code, which creates your DocumentPage
objects. These objects contain a Visual
, which you can go ahead and display in your UI.
您已经获得了用于创建DocumentPage
对象的分页代码。这些对象包含一个Visual
,您可以继续并在您的 UI 中显示它。
What you'll end up doing, is paginating your entire document, collecting all the DocumentPage
objects, then displaying their visuals inside of a scrolling StackPanel
or something similar. These are the same DocumentPage
objects that you can then send to the printer.
您最终要做的是对整个文档进行分页,收集所有DocumentPage
对象,然后在滚动StackPanel
或类似内容中显示它们的视觉效果。这些是DocumentPage
您随后可以发送到打印机的相同对象。
回答by Bobsum
The following code uses a MemoryStream to do a print preview.
以下代码使用 MemoryStream 进行打印预览。
MemoryStream stream = new MemoryStream();
Package package = Package.Open(stream, FileMode.Create, FileAccess.ReadWrite);
var uri = new Uri(@"memorystream://myXps.xps");
PackageStore.AddPackage(uri, package);
var xpsDoc = new XpsDocument(package);
xpsDoc.Uri = uri;
XpsDocument.CreateXpsDocumentWriter(xpsDoc).Write(paginator);
documentViewer.Document = xpsDoc.GetFixedDocumentSequence();
Remember to use close() and remove package from PackageStore when the print preview is closed.
请记住在关闭打印预览时使用 close() 并从 PackageStore 中删除包。
回答by pnb
XpsDocument doc = new XpsDocument("filename.xps", FileAccess.Read);
docViewer.Document = doc.GetFixedDocumentSequence();
doc.Close();