C# WPF 项目中集成 Pdf查看器

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

在工具箱中手动添加控件(可选)

虽然不能直接拖拽,但你可以:

  1. 创建自定义控件库:将 PdfViewerWrapper 控件编译为独立的 DLL
  2. 添加到工具箱
    • 右键点击工具箱 → "选择项"
    • 浏览并选择你的控件 DLL
    • 控件将出现在工具箱中

总结

在 WPF 中使用 PdfiumViewer 的关键步骤:

  1. 安装 NuGet 包:PdfiumViewer 及其 Native 包
  2. 使用 WindowsFormsHost:承载 WinForms 控件
  3. 代码创建控件:在代码后台或自定义用户控件中实例化 PdfViewer
  4. 加载 PDF :使用 PdfDocument.Load() 方法

虽然不能像 WinForms 那样直接在工具箱中拖拽,但通过创建自定义用户控件,你可以在 WPF 中获得类似的开发体验。

相关推荐
kylezhao20191 天前
C# 文件的输入与输出(I/O)详解
java·算法·c#
kylezhao20191 天前
C# TreeView 控件详解与应用
c#
FL16238631291 天前
C# winform部署yolo26-obb旋转框检测的onnx模型演示源码+模型+说明
开发语言·c#
hoiii1872 天前
C# 俄罗斯方块游戏
开发语言·游戏·c#
chao1898442 天前
C#实现OMRON FINS-TCP协议与PLC通信
网络·tcp/ip·c#
ytttr8732 天前
基于C# WinForms实现多窗口通信
开发语言·microsoft·c#
fengfuyao9852 天前
基于C# WinForm实现的串口调试助手源码
开发语言·c#
上海物联网2 天前
Prism WPF中的自定义区域适配器解决了什么问题?在项目中怎么实现一个自定义适配器
wpf
weixin_421994782 天前
认识数据 - 变量与数据类型
c#·.net·.netcore
mudtools2 天前
深入理解飞书 Webhook 签名验证:一次踩坑到填坑的完整记录
网络·c#·.net·飞书