多页自定义打印及打印设置管理
发布时间: 2025-08-15 00:47:42 订阅数: 19 


WPF in C# 2008: 使用.NET 3.5的下一代Windows应用开发
### 多页自定义打印及打印设置管理
#### 多页自定义打印
在进行打印操作时,如果需要打印多页内容,由于视觉元素不能跨页显示,因此需要使用 `DocumentPaginator` 类,这与打印 `FlowDocument` 时使用的类相同。不过,这里需要从头开始创建 `DocumentPaginator`,并且没有内部的私有 `DocumentPaginator` 来处理所有繁重的工作。
实现 `DocumentPaginator` 的基本设计并不复杂。需要添加一个方法将内容分割成页面,并在内部存储这些页面的信息。然后,只需响应 `GetPage()` 方法,为 `PrintDialog` 提供所需的页面即可。每个页面以 `DrawingVisual` 的形式生成,并由 `DocumentPage` 类包装。
然而,将内容分割成页面是比较棘手的部分。WPF 并没有提供神奇的解决方案,需要自己决定如何分割内容。有些内容相对容易分割,比如长表格;而有些内容则比较困难,例如打印基于文本的长文档时,需要逐字遍历所有文本,将单词添加到行,再将行添加到页面,还需要测量每个单独的文本块,以确定其是否适合该行。如果想要实现类似于 `FlowDocument` 的最佳拟合对齐方式,最好使用 `PrintDialog.PrintDocument()` 方法,因为需要编写大量代码并使用一些非常专业的算法。
下面通过一个示例来演示一个不太困难的分页任务。将 `DataTable` 的内容以表格结构打印,每条记录放在单独的一行,根据所选字体在一页上能容纳的行数将行分割到不同页面。
```csharp
public class StoreDataSetPaginator : DocumentPaginator
{
private DataTable dt;
private Typeface typeface;
private double fontSize;
private double margin;
private Size pageSize;
public override Size PageSize
{
get { return pageSize; }
set
{
pageSize = value;
PaginateData();
}
}
public StoreDataSetPaginator(DataTable dt, Typeface typeface,
double fontSize, double margin, Size pageSize)
{
this.dt = dt;
this.typeface = typeface;
this.fontSize = fontSize;
this.margin = margin;
this.pageSize = pageSize;
PaginateData();
}
private int rowsPerPage;
private int pageCount;
private void PaginateData()
{
// Create a test string for the purposes of measurement.
FormattedText text = GetFormattedText("A");
// Count the lines that fit on a page.
rowsPerPage = (int)((pageSize.Height - margin * 2) / text.Height);
// Leave a row for the headings
rowsPerPage -= 1;
pageCount = (int)Math.Ceiling((double)dt.Rows.Count / rowsPerPage);
}
private FormattedText GetFormattedText(string text)
{
return GetFormattedText(text, typeface);
}
private FormattedText GetFormattedText(string text, Typeface typeface)
{
return new FormattedText(
text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
typeface, fontSize, Brushes.Black);
}
public override bool IsPageCountValid
{
get { return true; }
}
public override int PageCount
{
get { return pageCount; }
}
public override IDocumentPaginatorSource Source
{
get { return null; }
}
public override DocumentPage GetPage(int pageNumber)
{
// Create a test string for the purposes of measurement.
FormattedText text = GetFormattedText("A");
double col1_X = margin;
double col2_X = col1_X + text.Width * 15;
// Calculate the range of rows that fits on this page.
int minRow = pageNumber * rowsPerPage;
int maxRow = minRow + rowsPerPage;
// Create the visual for the page.
DrawingVisual visual = new DrawingVisual();
// Initial, set the position to the top-left corner of the printable area.
Point point = new Point(margin, margin);
using (DrawingContext dc = visual.RenderOpen())
{
// Draw the column headers.
Typeface columnHeaderTypeface = new Typeface(
typeface.FontFamily, FontStyles.Normal, FontWeights.Bold,
FontStretches.Normal);
point.X =
```
0
0
相关推荐









