Loading

在WPF中利用XPS文档实现打印功能

摘要

WPF重新规划了打印模型,将所有编码围绕System.Windows.Controls.PrintDialog,使用PrintDialog类可显示Print对话框、设置打印机首选项等等,并且可将元素、文档以及低级的可视化元素直接发送给打印机。在WPF中实现打印的方式也有好几种,本文将使用XPS的方式简单实现一下打印功能。

代码实现

1、准备FlowDocument模板以及模板中要显示的数据,之前已经分享过一篇该文章,传送门==>在WPF中将XAML文档转换为PDF文件导出 有需要跳转过去看一下,这里不再重复阐述

2、将数据填充至FlowDocument

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

3、使用Package开辟一个容器将模板写入

private FixedDocumentSequence _StudentDocument;
        /// <summary>
        /// 模板文档(绑定至前端要显示的文档视图中)
        /// </summary>
        public FixedDocumentSequence StudentDocument
        {
            get { return _StudentDocument; }
            set { _StudentDocument = value; RaisePropertyChanged(); }
        }


        private delegate void LoadXpsMethod();
        private MemoryStream ms;
        private Package package;
        private Uri DocumentUri;

        public MainWindowViewModel()
        {
            var doc = FillFlowDocument();
            Application.Current.Dispatcher.BeginInvoke(
                new LoadXpsMethod(() => FillDocumentViewer(doc)), DispatcherPriority.ApplicationIdle);
        }


        private void FillDocumentViewer(FlowDocument doc)
        {
            try
            {
                ms = new MemoryStream();
                package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
                DocumentUri = new Uri("pack://InMemoryDocument.xps");
                PackageStore.AddPackage(DocumentUri, package);
                XpsDocument xpsDocument = new XpsDocument(package, CompressionOption.Fast, DocumentUri.AbsoluteUri);
                XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
                writer.Write(((IDocumentPaginatorSource)doc).DocumentPaginator);
                StudentDocument = xpsDocument.GetFixedDocumentSequence();
                xpsDocument.Close();
            }
            catch (Exception e)
            {
                MessageBox.Show("读取打印模板错误:{0}", e.ToString());
            }
        }

简单说下思路,就是先加载文档模板,并通过设置上下文给模板绑定数据,开辟一个内存流,使用Package创建这个模板包,再写入到XPS文档中,最后通过XPS获取到一个FixedDocumentSequence文档序列绑定到前台。

4、最后记得做一下必要的释放

public void Dispose()
        {
            PackageStore.RemovePackage(DocumentUri);
            if (package != null)
            {
                package.Close();
                package = null;
            }
            if (ms != null)
            {
                ms.Close();
                ms = null;
            }
            DocumentUri = null;
        }

效果

  • 打印预览image-20221122224631645

  • 调起PrintDialog

    image-20221122224725975

  • 动效演示

    1

源代码

https://github.com/luchong0813/WPF_XPSDocumentPrint_Demo

posted @ 2022-11-22 23:13  傲慢与偏见luc  阅读(1411)  评论(0编辑  收藏  举报