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

300 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 文件加载和阅读器窗口管理。
```csharp
public interface IPdfViewerService : IDisposable
{
/// 通过文件路径打开 PDF 阅读器窗口
void OpenViewer(string filePath);
/// 通过文件流打开 PDF 阅读器窗口
void OpenViewer(Stream stream, string? title = null);
}
```
### IPdfPrintService - PDF 打印服务
负责 PDF 打印功能,包括静默打印和交互式打印。
```csharp
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
```csharp
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
```csharp
public void OpenPdfByStream()
{
// 从文件流打开 PDF(窗口标题可选)
using var stream = File.OpenRead(@"C:\Documents\UserManual.pdf");
_pdfViewerService.OpenViewer(stream, "用户手册.pdf");
}
```
### 3. 静默打印到指定打印机
```csharp
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. 打开打印设置对话框
```csharp
public void OpenPrintDialog()
{
// 显示打印设置对话框,用户确认后打印
bool userConfirmed = _printService.PrintWithDialog(@"C:\Documents\UserManual.pdf");
if (userConfirmed)
{
// 用户点击了"确定"按钮
}
else
{
// 用户点击了"取消"按钮
}
}
```
### 5. 打开打印预览
```csharp
public void ShowPrintPreview()
{
// 打开打印预览对话框
_printService.PrintPreview(@"C:\Documents\UserManual.pdf");
}
```
---
## DI 注册 | DI Registration
`CommonModule.RegisterTypes` 中已注册为单例服务:
```csharp
containerRegistry.RegisterSingleton<IPdfPrintService, PdfPrintService>();
containerRegistry.RegisterSingleton<IPdfViewerService, PdfViewerService>();
```
在 ViewModel 或 Service 中通过构造函数注入使用:
```csharp
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:主窗口添加"用户手册"按钮
```csharp
// 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 预览
```csharp
public void ExportAndPreview()
{
// 生成 PDF 报告到临时文件
var tempPath = Path.Combine(Path.GetTempPath(), $"Report_{DateTime.Now:yyyyMMdd_HHmmss}.pdf");
GenerateReport(tempPath);
// 自动打开 PDF 预览
_pdfViewerService.OpenViewer(tempPath);
}
```
### 场景 3:批量打印检测报告
```csharp
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
);
}
}
```