C# WPF 项目中集成 Pdf查看器
方法1:通过 NuGet 包安装并手动创建控件(推荐)
1. 安装 NuGet 包
xml
<!-- 在你的 WPF 项目的 .csproj 文件中添加 -->
<PackageReference Include="PdfiumViewer" Version="2.11.0" />
<PackageReference Include="PdfiumViewer.Native.x86_64.v8-xfa" Version="2023.6.12.1" />
或通过 NuGet 包管理器控制台:
powershell
Install-Package PdfiumViewer
Install-Package PdfiumViewer.Native.x86_64.v8-xfa
2. 在 XAML 中设置 WindowsFormsHost
由于 PdfiumViewer 是 WinForms 控件,需要在 WPF 中使用 WindowsFormsHost:
xml
<!-- 在 MainWindow.xaml 中 -->
<Window x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
Title="PDF Viewer" Height="600" Width="800">
<Grid>
<WindowsFormsHost x:Name="pdfHost" Margin="10"/>
</Grid>
</Window>
3. 在代码后台创建和使用 PdfViewer
csharp
using System;
using System.Windows;
using PdfiumViewer;
using System.Windows.Forms.Integration;
namespace YourNamespace
{
public partial class MainWindow : Window
{
private PdfViewer pdfViewer;
public MainWindow()
{
InitializeComponent();
InitializePdfViewer();
}
private void InitializePdfViewer()
{
// 创建 PdfViewer 实例
pdfViewer = new PdfViewer();
pdfViewer.Dock = System.Windows.Forms.DockStyle.Fill;
// 将 PdfViewer 添加到 WindowsFormsHost
pdfHost.Child = pdfViewer;
}
// 打开 PDF 文件
private void OpenPdf(string filePath)
{
try
{
// 加载 PDF 文档
pdfViewer.Document = PdfDocument.Load(filePath);
}
catch (Exception ex)
{
MessageBox.Show($"打开 PDF 失败: {ex.Message}");
}
}
// 示例:在窗口加载时打开 PDF
private void Window_Loaded(object sender, RoutedEventArgs e)
{
OpenPdf(@"C:\path\to\your\document.pdf");
}
}
}
方法2:创建自定义 WPF 控件(更优雅)
1. 创建 PdfViewerWrapper 用户控件
xml
<!-- PdfViewerWrapper.xaml -->
<UserControl x:Class="YourNamespace.Controls.PdfViewerWrapper"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<WindowsFormsHost x:Name="host"/>
</Grid>
</UserControl>
csharp
// PdfViewerWrapper.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
using PdfiumViewer;
using System.Windows.Forms.Integration;
namespace YourNamespace.Controls
{
public partial class PdfViewerWrapper : UserControl
{
private PdfViewer pdfViewer;
public PdfViewerWrapper()
{
InitializeComponent();
InitializePdfViewer();
}
private void InitializePdfViewer()
{
pdfViewer = new PdfViewer
{
Dock = System.Windows.Forms.DockStyle.Fill
};
host.Child = pdfViewer;
}
// 打开 PDF 文件
public void LoadPdf(string filePath)
{
try
{
pdfViewer.Document = PdfDocument.Load(filePath);
}
catch (Exception ex)
{
MessageBox.Show($"加载 PDF 失败: {ex.Message}");
}
}
// 从字节数组加载
public void LoadPdf(byte[] pdfData)
{
try
{
pdfViewer.Document = PdfDocument.Load(pdfData);
}
catch (Exception ex)
{
MessageBox.Show($"加载 PDF 失败: {ex.Message}");
}
}
// 从流加载
public void LoadPdf(System.IO.Stream stream)
{
try
{
pdfViewer.Document = PdfDocument.Load(stream);
}
catch (Exception ex)
{
MessageBox.Show($"加载 PDF 失败: {ex.Message}");
}
}
// 获取当前页面索引
public int GetCurrentPage()
{
return pdfViewer?.Renderer?.Page ?? 0;
}
// 跳转到指定页面
public void GoToPage(int page)
{
if (pdfViewer?.Renderer != null && page >= 0 && page < pdfViewer.Document.PageCount)
{
pdfViewer.Renderer.Page = page;
}
}
}
}
2. 在主窗口中使用自定义控件
xml
<!-- MainWindow.xaml -->
<Window x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:YourNamespace.Controls"
Title="PDF Viewer" Height="600" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 工具栏 -->
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="10">
<Button Content="打开 PDF" Click="OpenPdfButton_Click" Margin="5"/>
<Button Content="上一页" Click="PrevPageButton_Click" Margin="5"/>
<Button Content="下一页" Click="NextPageButton_Click" Margin="5"/>
<TextBlock Text="页码:" VerticalAlignment="Center" Margin="10,0,5,0"/>
<TextBlock x:Name="pageInfo" VerticalAlignment="Center"/>
</StackPanel>
<!-- PDF 查看器 -->
<controls:PdfViewerWrapper x:Name="pdfViewerControl" Grid.Row="1"/>
</Grid>
</Window>
csharp
// MainWindow.xaml.cs
using Microsoft.Win32;
using System.Windows;
namespace YourNamespace
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OpenPdfButton_Click(object sender, RoutedEventArgs e)
{
var openFileDialog = new OpenFileDialog
{
Filter = "PDF 文件|*.pdf|所有文件|*.*",
Title = "选择 PDF 文件"
};
if (openFileDialog.ShowDialog() == true)
{
pdfViewerControl.LoadPdf(openFileDialog.FileName);
}
}
private void PrevPageButton_Click(object sender, RoutedEventArgs e)
{
int currentPage = pdfViewerControl.GetCurrentPage();
if (currentPage > 0)
{
pdfViewerControl.GoToPage(currentPage - 1);
}
}
private void NextPageButton_Click(object sender, RoutedEventArgs e)
{
int currentPage = pdfViewerControl.GetCurrentPage();
pdfViewerControl.GoToPage(currentPage + 1);
}
}
}
方法3:使用 PdfRenderer 而不是 PdfViewer
如果你只需要简单的 PDF 渲染(没有工具栏),可以使用 PdfRenderer:
csharp
using System.Windows;
using System.Windows.Forms.Integration;
using PdfiumViewer;
public partial class MainWindow : Window
{
private PdfRenderer pdfRenderer;
public MainWindow()
{
InitializeComponent();
InitializePdfRenderer();
}
private void InitializePdfRenderer()
{
pdfRenderer = new PdfRenderer();
pdfRenderer.Dock = System.Windows.Forms.DockStyle.Fill;
pdfRenderer.ZoomMode = PdfViewerZoomMode.FitWidth;
// 添加到 WindowsFormsHost
var host = new WindowsFormsHost();
host.Child = pdfRenderer;
// 添加到 WPF 容器
contentContainer.Children.Add(host);
}
private void LoadPdf(string filePath)
{
var document = PdfDocument.Load(filePath);
pdfRenderer.Load(document);
}
}
解决常见问题
问题1:找不到 PdfiumViewer 控件
- 原因:PdfiumViewer 是 WinForms 控件,不会自动出现在 WPF 工具箱中
- 解决方案:手动创建控件实例,如上所示
问题2:运行时异常(DLL 未找到)
xml
<!-- 在 .csproj 中确保包含 Native 包 -->
<PackageReference Include="PdfiumViewer.Native.x86_64.v8-xfa" Version="2023.6.12.1" />
<!-- 或 x86 版本 -->
<PackageReference Include="PdfiumViewer.Native.x86.v8-xfa" Version="2023.6.12.1" />
问题3:设计时看不到控件
- 原因:WinForms 控件在 WPF 设计器中不可见
- 解决方案:在设计时显示占位符,运行时加载真实控件
xml
<!-- 在设计时显示标签,运行时替换 -->
<UserControl>
<Grid>
<TextBlock x:Name="designText"
Text="PDF Viewer (设计时)"
Visibility="{Binding IsInDesignMode, Converter={StaticResource BoolToVisibilityConverter}}"/>
<WindowsFormsHost x:Name="host"
Visibility="{Binding IsInDesignMode, Converter={StaticResource BoolToVisibilityInverseConverter}}"/>
</Grid>
</UserControl>
完整示例项目结构
YourSolution/
├── YourWpfProject/
│ ├── Controls/
│ │ ├── PdfViewerWrapper.xaml
│ │ └── PdfViewerWrapper.xaml.cs
│ ├── MainWindow.xaml
│ ├── MainWindow.xaml.cs
│ └── YourWpfProject.csproj
└── YourWpfProject.sln
在工具箱中手动添加控件(可选)
虽然不能直接拖拽,但你可以:
- 创建自定义控件库:将 PdfViewerWrapper 控件编译为独立的 DLL
- 添加到工具箱 :
- 右键点击工具箱 → "选择项"
- 浏览并选择你的控件 DLL
- 控件将出现在工具箱中
总结
在 WPF 中使用 PdfiumViewer 的关键步骤:
- 安装 NuGet 包:PdfiumViewer 及其 Native 包
- 使用 WindowsFormsHost:承载 WinForms 控件
- 代码创建控件:在代码后台或自定义用户控件中实例化 PdfViewer
- 加载 PDF :使用
PdfDocument.Load()方法
虽然不能像 WinForms 那样直接在工具箱中拖拽,但通过创建自定义用户控件,你可以在 WPF 中获得类似的开发体验。