Files
XplorePlane/XP.Common/Documents/PdfViewer.README.md
T

9.0 KiB
Raw Blame History

PDF 查看与打印模块使用指南 | PDF Viewer & Printer Module Usage Guide

概述 | Overview

XP.Common.PdfViewer 提供基于 Telerik RadPdfViewer 的 PDF 文件查看与打印功能模块。模块作为 XP.Common 的通用可复用组件,通过 Prism DI 容器注册服务接口,供外部类库通过构造函数注入使用。

核心功能 | Core Features

  • PDF 文件加载与显示(支持文件路径和文件流两种方式)
  • 内置 RadPdfViewerToolbar 提供页面导航、缩放、旋转、打印等完整工具栏 UI
  • 静默打印(指定打印机、页面范围、打印份数)
  • 打印设置对话框(用户交互式配置打印参数)
  • 打印预览功能
  • 多语言支持(简体中文、繁体中文、英文)
  • 结构化日志记录(使用 ILoggerService
  • 资源自动释放(IDisposable + 终结器安全网)

目录结构 | Directory Structure

XP.Common/PdfViewer/
├── Exceptions/                    # 自定义异常
│   ├── PdfLoadException.cs        # PDF 加载异常
│   ├── PrinterNotFoundException.cs # 打印机未找到异常
│   └── PrintException.cs          # 打印异常
├── Interfaces/                    # 服务接口
│   ├── IPdfViewerService.cs       # PDF 查看服务接口
│   └── IPdfPrintService.cs        # PDF 打印服务接口
├── Implementations/              # 服务实现
│   ├── PdfViewerService.cs        # PdfViewerService 实现
│   └── PdfPrintService.cs         # PdfPrintService 实现
├── ViewModels/                    # ViewModel
│   └── PdfViewerWindowViewModel.cs # 阅读器窗口 ViewModel
└── Views/                         # 视图
    ├── PdfViewerWindow.xaml       # 阅读器窗口 XAML
    └── PdfViewerWindow.xaml.cs    # 阅读器窗口 Code-Behind

服务接口 | Service Interfaces

IPdfViewerService - PDF 查看服务

负责 PDF 文件加载和阅读器窗口管理。

public interface IPdfViewerService : IDisposable
{
    /// 通过文件路径打开 PDF 阅读器窗口
    void OpenViewer(string filePath);

    /// 通过文件流打开 PDF 阅读器窗口
    void OpenViewer(Stream stream, string? title = null);
}

IPdfPrintService - PDF 打印服务

负责 PDF 打印功能,包括静默打印和交互式打印。

public interface IPdfPrintService
{
    /// 使用指定打印机打印 PDF 文件
    void Print(string filePath, string printerName, int? pageFrom = null, int? pageTo = null, int copies = 1);

    /// 打开打印设置对话框并打印
    bool PrintWithDialog(string filePath);

    /// 打开打印预览对话框
    void PrintPreview(string filePath);
}

使用示例 | Usage Examples

1. 通过文件路径打开 PDF

using XP.Common.PdfViewer.Interfaces;

public class MyService
{
    private readonly IPdfViewerService _pdfViewerService;

    public MyService(IPdfViewerService pdfViewerService)
    {
        _pdfViewerService = pdfViewerService;
    }

    public void OpenPdfByPath()
    {
        // 打开指定路径的 PDF 文件
        _pdfViewerService.OpenViewer(@"C:\Documents\UserManual.pdf");
    }
}

2. 通过文件流打开 PDF

public void OpenPdfByStream()
{
    // 从文件流打开 PDF(窗口标题可选)
    using var stream = File.OpenRead(@"C:\Documents\UserManual.pdf");
    _pdfViewerService.OpenViewer(stream, "用户手册.pdf");
}

3. 静默打印到指定打印机

using XP.Common.PdfViewer.Interfaces;

public class MyService
{
    private readonly IPdfPrintService _printService;

    public MyService(IPdfPrintService printService)
    {
        _printService = printService;
    }

    public void PrintPdf()
    {
        // 打印全部页面到指定打印机
        _printService.Print(
            filePath: @"C:\Documents\UserManual.pdf",
            printerName: "HP LaserJet Pro",
            pageFrom: null,  // null 表示从第一页
            pageTo: null,    // null 表示到最后一页
            copies: 1        // 打印 1 份
        );

        // 打印指定范围(第 1-3 页)
        _printService.Print(
            filePath: @"C:\Documents\UserManual.pdf",
            printerName: "HP LaserJet Pro",
            pageFrom: 1,
            pageTo: 3,
            copies: 2
        );
    }
}

4. 打开打印设置对话框

public void OpenPrintDialog()
{
    // 显示打印设置对话框,用户确认后打印
    bool userConfirmed = _printService.PrintWithDialog(@"C:\Documents\UserManual.pdf");
    
    if (userConfirmed)
    {
        // 用户点击了"确定"按钮
    }
    else
    {
        // 用户点击了"取消"按钮
    }
}

5. 打开打印预览

public void ShowPrintPreview()
{
    // 打开打印预览对话框
    _printService.PrintPreview(@"C:\Documents\UserManual.pdf");
}

DI 注册 | DI Registration

CommonModule.RegisterTypes 中已注册为单例服务:

containerRegistry.RegisterSingleton<IPdfPrintService, PdfPrintService>();
containerRegistry.RegisterSingleton<IPdfViewerService, PdfViewerService>();

在 ViewModel 或 Service 中通过构造函数注入使用:

public class MyViewModel
{
    private readonly IPdfViewerService _pdfViewerService;
    private readonly IPdfPrintService _printService;

    public MyViewModel(
        IPdfViewerService pdfViewerService,
        IPdfPrintService printService)
    {
        _pdfViewerService = pdfViewerService;
        _printService = printService;
    }
}

多语言资源 | Localization Resources

PDF 模块支持多语言,资源键如下:

资源键 zh-CN zh-TW en-US
PdfViewer_Title PDF 阅读器 PDF 閱讀器 PDF Viewer
PdfViewer_TitleWithFile PDF 阅读器 - {0} PDF 閱讀器 - {0} PDF Viewer - {0}
PdfViewer_LoadSuccess PDF 文件加载成功:{0}({1} 页) PDF 檔案載入成功:{0}({1} 頁) PDF loaded: {0} ({1} pages)
PdfViewer_LoadFailed PDF 文件加载失败 PDF 檔案載入失敗 PDF file load failed
PdfViewer_PrintSuccess 打印任务已提交:{0} → {1} 列印任務已提交:{0} → {1} Print job submitted: {0} → {1}
PdfViewer_PrintFailed 打印失败 列印失敗 Print failed
PdfViewer_PrinterNotFound 打印机未找到:{0} 印表機未找到:{0} Printer not found: {0}

异常处理 | Exception Handling

异常类型 触发条件 说明
FileNotFoundException 文件路径不存在 OpenViewer(filePath)Print(filePath, ...)
ArgumentNullException 流参数为 null OpenViewer(null, ...)
PdfLoadException PDF 格式无效或加载失败 文件损坏、非 PDF 格式等
PrinterNotFoundException 指定打印机不存在 Print(filePath, printerName, ...)
PrintException 打印过程中发生错误 打印机错误、驱动问题等

注意事项 | Notes

  1. RadPdfViewerToolbar 内置功能:页面导航(首页/上一页/下一页/末页)、缩放(放大/缩小/适合宽度/适合整页)、旋转(顺时针/逆时针)等功能由 RadPdfViewerToolbar 自动提供,无需手动实现。

  2. 资源释放PdfViewerService 实现 IDisposable,窗口闭时会自动释放 PDF 文档资源。终结器作为安全网,确保未显式释放时也能清理资源。

  3. 多语言支持RadPdfViewerToolbar 的内置按钮文本(如"首页"、"上一页"、"放大"等)由 Telerik 自身的本地化机制管理,无需在 XP.Common 的 Resources 中维护。

  4. 打印设置Telerik 提供内置的 PrintSettings 类,无需自定义打印设置模型。

  5. 日志记录:所有关键操作(加载成功/失败、打印成功/失败)都会通过 ILoggerService 记录结构化日志。


典型应用场景 | Typical Use Cases

场景 1:主窗口添加"用户手册"按钮

// MainWindowViewModel.cs
private void ExecuteOpenUserManual()
{
    var manualPath = ConfigurationManager.AppSettings["UserManual"];
    var stream = File.OpenRead(manualPath);
    var fileName = Path.GetFileName(manualPath);
    _pdfViewerService.OpenViewer(stream, fileName);
}

场景 2:导出报告后自动打开 PDF 预览

public void ExportAndPreview()
{
    // 生成 PDF 报告到临时文件
    var tempPath = Path.Combine(Path.GetTempPath(), $"Report_{DateTime.Now:yyyyMMdd_HHmmss}.pdf");
    GenerateReport(tempPath);

    // 自动打开 PDF 预览
    _pdfViewerService.OpenViewer(tempPath);
}

场景 3:批量打印检测报告

public void BatchPrintReports(List<string> reportPaths, string printerName)
{
    foreach (var path in reportPaths)
    {
        _printService.Print(
            filePath: path,
            printerName: printerName,
            pageFrom: 1,
            pageTo: null,
            copies: 1
        );
    }
}