将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。

This commit is contained in:
QI Mingxuan
2026-04-16 17:31:13 +08:00
parent 6ec4c3ddaa
commit 2bd6e566c3
581 changed files with 74600 additions and 222 deletions
@@ -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;
}
}
}