WPF中如何在FlowDocument每页打印页码?哪种方式最优?
FlowDocument打印时添加页码的最优实现方案
要给FlowDocument打印页添加动态页码,最优方式是通过自定义DocumentPaginator实现,原因如下:
- 直接在FlowDocument中静态添加文本无法动态获取当前页号和总页数,流式内容的分页逻辑是运行时确定的;
PrintDialog仅负责触发打印流程,不处理文档内容的渲染和分页逻辑,无法通过它添加页码。
实现步骤
- 自定义一个继承自
DocumentPaginator的类,重写GetPage方法,在每页内容的基础上添加页码; - 打印时用这个自定义分页器包装原FlowDocument的分页器,再传入
PrintDialog。
完整代码示例
自定义分页器类
using System.Windows; using System.Windows.Documents; using System.Windows.Media; using System.Globalization; public class PaginatedFlowDocumentPaginator : DocumentPaginator { private readonly DocumentPaginator _originalPaginator; private readonly Typeface _pageNumberTypeface; private readonly double _pageNumberFontSize; public PaginatedFlowDocumentPaginator(DocumentPaginator originalPaginator) { _originalPaginator = originalPaginator; _pageNumberTypeface = new Typeface("Segoe UI"); _pageNumberFontSize = 10; } public override DocumentPage GetPage(int pageNumber) { // 获取原分页器生成的页面 DocumentPage originalPage = _originalPaginator.GetPage(pageNumber); // 创建新的Visual容器,用于合并原页面内容和页码 DrawingVisual pageVisual = new DrawingVisual(); using (DrawingContext dc = pageVisual.RenderOpen()) { // 绘制原页面内容 VisualBrush originalContentBrush = new VisualBrush(originalPage.Visual); dc.DrawRectangle(originalContentBrush, null, new Rect(originalPage.Size)); // 生成页码文本 string pageText = $"第 {pageNumber + 1} 页 / 共 {PageCount} 页"; FormattedText formattedPageText = new FormattedText( pageText, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, _pageNumberTypeface, _pageNumberFontSize, Brushes.Black); // 设置页码位置(右下角,留15px边距) double margin = 15; Point pageTextPosition = new Point( originalPage.Size.Width - formattedPageText.Width - margin, originalPage.Size.Height - formattedPageText.Height - margin); dc.DrawText(formattedPageText, pageTextPosition); } // 返回包含页码的新页面 return new DocumentPage( pageVisual, originalPage.Size, originalPage.BleedBox, originalPage.ContentBox); } // 代理原分页器的属性,保持原有分页逻辑 public override bool IsPageCountValid => _originalPaginator.IsPageCountValid; public override int PageCount => _originalPaginator.PageCount; public override Size PageSize { get => _originalPaginator.PageSize; set => _originalPaginator.PageSize = value; } public override IDocumentPaginatorSource Source => _originalPaginator.Source; }
修改打印按钮事件
private void Btn_print_Click(object sender, RoutedEventArgs e) { PrintDialog pd = new PrintDialog(); if (pd.ShowDialog() == true) { // 使用自定义分页器包装原FlowDocument的分页器 var paginatorWithPageNumbers = new PaginatedFlowDocumentPaginator(FlowDoc.DocumentPaginator); pd.PrintDocument(paginatorWithPageNumbers, "带页码的Flow Document"); } }
额外优化点
- 可以将页码的字体、颜色、位置做成可配置参数,适配不同需求;
- 如果原文档页脚有内容,可调整页码的Y坐标避免重叠;
- 支持横向打印:通过判断
PageSize的宽高比调整页码位置。
内容的提问来源于stack exchange,提问作者Costa
相关产品推荐
相关产品推荐

