将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
<Window x:Class="XP.Common.PdfViewer.Views.PdfViewerWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
|
||||
xmlns:converters="clr-namespace:Telerik.Windows.Documents.Converters;assembly=Telerik.Windows.Controls.FixedDocumentViewers"
|
||||
Title="{Binding Title}"
|
||||
Width="1024" Height="768"
|
||||
MinWidth="800" MinHeight="600"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
ShowInTaskbar="True"
|
||||
WindowStyle="SingleBorderWindow">
|
||||
|
||||
<Window.Resources>
|
||||
<!-- 缩略图转换器:将 RadFixedDocument 转换为缩略图集合 | Thumbnail converter: converts RadFixedDocument to thumbnails collection -->
|
||||
<converters:ThumbnailsConverter x:Key="ThumbnailsConverter" ThumbnailsHeight="200"/>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<!-- 工具栏(RadPdfViewerToolbar 内置导航/缩放/旋转/打印)| Toolbar (built-in navigation/zoom/rotate/print) -->
|
||||
<RowDefinition Height="Auto"/>
|
||||
<!-- PDF 显示区域 | PDF display area -->
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Telerik 内置工具栏 | Built-in toolbar -->
|
||||
<telerik:RadPdfViewerToolBar Grid.Row="0"
|
||||
telerik:StyleManager.Theme="Crystal"
|
||||
RadPdfViewer="{Binding ElementName=pdfViewer, Mode=OneTime}"/>
|
||||
|
||||
<!-- 主内容区域:左侧缩略图面板 + 右侧 PDF 显示 | Main content: left thumbnails + right PDF display -->
|
||||
<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<!-- 左侧缩略图面板 | Left thumbnails panel -->
|
||||
<ColumnDefinition Width="180"/>
|
||||
<!-- PDF 显示区域 | PDF display area -->
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- 页面缩略图面板 | Page thumbnails panel -->
|
||||
<Border Grid.Column="0" BorderBrush="#DDDDDD" BorderThickness="0,0,1,0" Background="#F5F5F5">
|
||||
<ListBox x:Name="thumbnailListBox"
|
||||
ItemsSource="{Binding ElementName=pdfViewer, Path=Document, Converter={StaticResource ThumbnailsConverter}}"
|
||||
SelectionChanged="ThumbnailListBox_SelectionChanged"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Padding="4">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="2,4" HorizontalAlignment="Center">
|
||||
<!-- 缩略图图片 | Thumbnail image -->
|
||||
<Border BorderBrush="#CCCCCC" BorderThickness="1" Background="White"
|
||||
HorizontalAlignment="Center">
|
||||
<Image Source="{Binding ImageSource}" Stretch="Uniform"
|
||||
MaxWidth="150" MaxHeight="200"/>
|
||||
</Border>
|
||||
<!-- 页码 | Page number -->
|
||||
<TextBlock Text="{Binding PageNumber}"
|
||||
HorizontalAlignment="Center" Margin="0,2,0,0"
|
||||
FontSize="11" Foreground="#666666"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Border>
|
||||
|
||||
<!-- PDF 渲染区域 | PDF rendering area -->
|
||||
<telerik:RadPdfViewer Grid.Column="1"
|
||||
x:Name="pdfViewer"
|
||||
telerik:StyleManager.Theme="Crystal"
|
||||
DataContext="{Binding ElementName=pdfViewer, Path=CommandDescriptors}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,132 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
public partial class PdfViewerWindow : Window
|
||||
{
|
||||
// 防止缩略图选择和页面跳转之间的循环触发 | Prevent circular trigger between thumbnail selection and page navigation
|
||||
private bool _isSyncingSelection;
|
||||
|
||||
public PdfViewerWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
Closed += OnClosed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口加载事件:通过 PdfFormatProvider 加载 PDF 文档到 RadPdfViewer
|
||||
/// Window loaded event: load PDF document into RadPdfViewer via PdfFormatProvider
|
||||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 缩略图列表选择变化:跳转到对应页面 | Thumbnail selection changed: navigate to corresponding page
|
||||
/// ListBox.SelectedIndex 从 0 开始,RadPdfViewer.CurrentPageNumber 从 1 开始
|
||||
/// ListBox.SelectedIndex is 0-based, RadPdfViewer.CurrentPageNumber is 1-based
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PDF 阅读器页面变化:同步缩略图选中状态 | PDF viewer page changed: sync thumbnail selection
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 窗口关闭事件:释放 RadPdfViewer 文档资源
|
||||
/// Window closed event: release RadPdfViewer document resources
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user