You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中如何在FlowDocument每页打印页码?哪种方式最优?

FlowDocument打印时添加页码的最优实现方案

要给FlowDocument打印页添加动态页码,最优方式是通过自定义DocumentPaginator实现,原因如下:

  • 直接在FlowDocument中静态添加文本无法动态获取当前页号和总页数,流式内容的分页逻辑是运行时确定的;
  • PrintDialog仅负责触发打印流程,不处理文档内容的渲染和分页逻辑,无法通过它添加页码。

实现步骤

  1. 自定义一个继承自DocumentPaginator的类,重写GetPage方法,在每页内容的基础上添加页码;
  2. 打印时用这个自定义分页器包装原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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:34:56