Loading

在WPF中将XAML文档转换为PDF文件导出

编写文档模板页面

1、新建Page页面,将顶部节点更改为FlowDocument,后台代码不需要,可直接删掉

image-20221116220143007

image-20221116222016029

2、实现一个表格页面

直接上代码,自己看,其中需要注意的是,如果非静态页面(即内容是需要绑定的),只需要给它一个DataContext上下文即可,后文会有讲到

<FlowDocument
    x:Class="wpf_xaml2pdf_demo.Resources.StudentTemplate"
    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:local="clr-namespace:wpf_xaml2pdf_demo.Resources"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <FlowDocument.Resources>
        <Style x:Key="BorderedTable" TargetType="Table">
            <Setter Property="CellSpacing" Value="0" />
            <Setter Property="BorderThickness" Value="1" />
            <Setter Property="BorderBrush" Value="#000" />
        </Style>
        <Style x:Key="BorderedCell" TargetType="TableCell">
            <Setter Property="BorderThickness" Value="0.5" />
            <Setter Property="BorderBrush" Value="#000" />
            <Setter Property="Padding" Value="10" />
        </Style>
    </FlowDocument.Resources>
    <Table FontSize="25" Style="{StaticResource BorderedTable}">
        <Table.Columns>
            <TableColumn Width="784" />
            <TableColumn Width="300" />
        </Table.Columns>
        <TableRowGroup>
            <TableRow>
                <TableCell ColumnSpan="2" FontSize="40">
                    <Paragraph Margin="30" TextAlignment="Center">
                        学生成绩单
                    </Paragraph>
                </TableCell>
            </TableRow>
            <TableRow>
                <TableCell ColumnSpan="2">
                    <Table
                        Margin="20,20,20,0"
                        FontSize="25"
                        Style="{StaticResource BorderedTable}">
                        <Table.Columns>
                            <TableColumn Width="200" />
                            <TableColumn />
                        </Table.Columns>
                        <TableRowGroup>
                            <TableRow>
                                <TableCell ColumnSpan="2" Style="{StaticResource BorderedCell}">
                                    <Paragraph FontSize="25" TextAlignment="Center">
                                        学生成绩信息
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph TextAlignment="Right">
                                        姓名
                                    </Paragraph>
                                </TableCell>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph>
                                        <Run Text="{Binding Name}" />
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph TextAlignment="Right">
                                        班级
                                    </Paragraph>
                                </TableCell>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph>
                                        <Run Text="{Binding Class}" />
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph TextAlignment="Right">
                                        语文成绩
                                    </Paragraph>
                                </TableCell>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph>
                                        <Run Text="{Binding Chinese}" />
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph TextAlignment="Right">
                                        数学成绩
                                    </Paragraph>
                                </TableCell>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph>
                                        <Run Text="{Binding Math}" />
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph TextAlignment="Right">
                                        英语成绩
                                    </Paragraph>
                                </TableCell>
                                <TableCell Style="{StaticResource BorderedCell}">
                                    <Paragraph>
                                        <Run Text="{Binding English}" />
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                        </TableRowGroup>
                    </Table>
                </TableCell>
            </TableRow>
            <TableRow>
                <TableCell ColumnSpan="2">
                    <Table
                        Margin="20,0,20,20"
                        FontSize="25"
                        Style="{StaticResource BorderedTable}">
                        <Table.Columns>
                            <TableColumn />
                        </Table.Columns>
                        <TableRowGroup>
                            <TableRow>
                                <TableCell ColumnSpan="2" Style="{StaticResource BorderedCell}">
                                    <Paragraph FontSize="25" TextAlignment="Left">
                                        班主任评语
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                            <TableRow>
                                <TableCell ColumnSpan="2" Style="{StaticResource BorderedCell}">
                                    <Paragraph TextAlignment="Center">
                                        <Run Text="{Binding Comments}" />
                                    </Paragraph>
                                </TableCell>
                            </TableRow>
                        </TableRowGroup>
                    </Table>
                </TableCell>
            </TableRow>
        </TableRowGroup>
    </Table>
</FlowDocument>

后台逻辑

1、导出按钮命令

public MainWindowViewModel()
        {
            ExportCommand = new DelegateCommand(ExportPdfMethod);
        }
        
 private delegate void DoExportPdfMethod();
 
 public DelegateCommand ExportCommand { get; set; }
 
 //线程同步
 private void ExportPdfMethod()
        {
            Application.Current.Dispatcher.BeginInvoke(
                new DoExportPdfMethod(() => SavePDF()),
                DispatcherPriority.ApplicationIdle
                );
        }

2、加载并填充模板数据

private FlowDocument FillFlowDocument()
        {
            FlowDocument doc = (FlowDocument)Application.LoadComponent(new Uri("/wpf_xaml2pdf_demo;component/Resources/StudentTemplate.xaml", UriKind.RelativeOrAbsolute));
            doc.DataContext = new Models.Student
            {
                Name = "傲慢与偏见",
                Class = "三年一班",
                Chinese = 99,
                Math = 59,
                English = 66,
                Comments = "此乃难得一见的奇才,未来可期!!!(Tips:这文字是绑定的,不是静态数据)"
            };
            return doc;
        }

Tips:这里使用Application.LoadComponent加载模板文件,并显示转换为FlowDocument,上文所说的可以删除后台文件,就是因为可以直接对该文档设置上下文,给它一个模型实体,模板xaml那边正常使用Binding即可

3、弹窗并转换文档为pdf

private void SavePDF()
        {
            try
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();
                saveFileDialog.Filter = "(*.pdf)|*.pdf";
                saveFileDialog.FileName = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                //填充模板
                if (studentTemplate == null)
                {
                    studentTemplate = FillFlowDocument();
                }
                if (saveFileDialog.ShowDialog() == true)
                {
                    string xpsPath = Path.Combine(Environment.GetEnvironmentVariable("TEMP"), $"Xps_{DateTime.Now:yyyyMMddHHmmssfff}.xps");
                    using (XpsDocument xpsDocument = new XpsDocument(xpsPath, FileAccess.Write))
                    {
                        XpsDocumentWriter documentwriter = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
                        documentwriter.Write(((IDocumentPaginatorSource)studentTemplate).DocumentPaginator);
                    }
                    PdfSharp.Xps.XpsConverter.Convert(xpsPath, saveFileDialog.FileName, 0);
                    DeletedInvalidFile(xpsPath);
                    MessageBox.Show($"PDF文件保存成功,路径:{saveFileDialog.FileName}");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存PDF时发生异常:{ex}");
            }
        }

Tips:这里主要分为3步,先弹出一个文件保存对话框让用户选择,再将模板文件写入到一个临时目录xps中间文件,最后掉了个库将文档转换为pdf保存即可。

效果演示

1

代码

https://github.com/luchong0813/wpf_xaml2pdf_demo

posted @ 2022-11-16 23:20  傲慢与偏见luc  阅读(1601)  评论(1编辑  收藏  举报