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 中获得类似的开发体验。

相关推荐
时光追逐者2 小时前
ASP.NET Core 依赖注入的三种服务生命周期
后端·c#·asp.net·.net·.netcore
wuguan_2 小时前
C#显示转换和隐式转换
c#·显示转换和隐式转换
wuguan_2 小时前
C#:try和catch(保护程序不崩溃)
开发语言·c#·try catch
黑贝是条狗2 小时前
Delphi TCP通信帧设计,类型Websocket通信帧
开发语言·c#
kylezhao201911 小时前
第1章:第一节 开发环境搭建(工控场景最优配置)
开发语言·c#
liliangcsdn11 小时前
常用pdf解析提取工具的分析和示例
pdf
钰fly14 小时前
C#文件与数据操作核心概念手册
c#
阿蒙Amon14 小时前
C#每日面试题-简述C#访问修饰符
windows·microsoft·c#
Kiyra15 小时前
WebSocket vs HTTP:为什么 IM 系统选择长连接?
分布式·websocket·网络协议·http·设计模式·系统架构·wpf