using System; using System.IO; using System.Windows; using System.Windows.Controls; using Telerik.Windows.Documents.Fixed.FormatProviders.Pdf; using XP.Common.PdfViewer.Exceptions; using XP.Common.PdfViewer.ViewModels; namespace XP.Common.PdfViewer.Views { /// /// PDF 阅读器窗口 code-behind | PDF viewer window code-behind /// 负责在 Loaded 事件中加载 PDF 文档,在 Closed 事件中释放资源 /// Responsible for loading PDF document on Loaded event and releasing resources on Closed event /// public partial class PdfViewerWindow : Window { // 防止缩略图选择和页面跳转之间的循环触发 | Prevent circular trigger between thumbnail selection and page navigation private bool _isSyncingSelection; public PdfViewerWindow() { InitializeComponent(); Loaded += OnLoaded; Closed += OnClosed; } /// /// 窗口加载事件:通过 PdfFormatProvider 加载 PDF 文档到 RadPdfViewer /// Window loaded event: load PDF document into RadPdfViewer via PdfFormatProvider /// private void OnLoaded(object sender, RoutedEventArgs e) { var vm = DataContext as PdfViewerWindowViewModel; if (vm == null) return; try { var provider = new PdfFormatProvider(); if (vm.PdfStream != null) { // 从文件流加载 PDF | Load PDF from stream pdfViewer.Document = provider.Import(vm.PdfStream); } else if (!string.IsNullOrEmpty(vm.FilePath)) { // 从文件路径加载 PDF | Load PDF from file path using var stream = File.OpenRead(vm.FilePath); pdfViewer.Document = provider.Import(stream); } // 文档加载后,监听页面变化以同步缩略图选中状态 | After document loaded, listen for page changes to sync thumbnail selection pdfViewer.CurrentPageChanged += PdfViewer_CurrentPageChanged; // 初始选中第一页缩略图 | Initially select first page thumbnail if (thumbnailListBox.Items.Count > 0) { thumbnailListBox.SelectedIndex = 0; } } catch (Exception ex) when (ex is not PdfLoadException) { // 捕获加载异常并包装为 PdfLoadException | Catch loading exceptions and wrap as PdfLoadException throw new PdfLoadException( "PDF 文件加载失败 | PDF file load failed", vm.FilePath, ex); } } /// /// 缩略图列表选择变化:跳转到对应页面 | Thumbnail selection changed: navigate to corresponding page /// ListBox.SelectedIndex 从 0 开始,RadPdfViewer.CurrentPageNumber 从 1 开始 /// ListBox.SelectedIndex is 0-based, RadPdfViewer.CurrentPageNumber is 1-based /// private void ThumbnailListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (_isSyncingSelection) return; if (thumbnailListBox.SelectedIndex < 0) return; _isSyncingSelection = true; try { // SelectedIndex(0-based) + 1 = CurrentPageNumber(1-based) pdfViewer.CurrentPageNumber = thumbnailListBox.SelectedIndex + 1; } finally { _isSyncingSelection = false; } } /// /// PDF 阅读器页面变化:同步缩略图选中状态 | PDF viewer page changed: sync thumbnail selection /// private void PdfViewer_CurrentPageChanged(object? sender, EventArgs e) { if (_isSyncingSelection) return; _isSyncingSelection = true; try { // CurrentPageNumber(1-based) - 1 = SelectedIndex(0-based) var index = pdfViewer.CurrentPageNumber - 1; if (index >= 0 && index < thumbnailListBox.Items.Count) { thumbnailListBox.SelectedIndex = index; thumbnailListBox.ScrollIntoView(thumbnailListBox.SelectedItem); } } finally { _isSyncingSelection = false; } } /// /// 窗口关闭事件:释放 RadPdfViewer 文档资源 /// Window closed event: release RadPdfViewer document resources /// private void OnClosed(object? sender, EventArgs e) { // 取消事件订阅 | Unsubscribe events pdfViewer.CurrentPageChanged -= PdfViewer_CurrentPageChanged; // RadPdfViewer 内部管理文档资源,设置 Document = null 触发释放 // RadPdfViewer internally manages document resources, setting Document = null triggers release pdfViewer.Document = null; } } }