wpf中xps文档合并功能实现
跟着上一篇的xps文档套打的文章,近期一直在研究xps打印技术,其中用户提到了一个需求,要求能够多页面进行打印,我的想法是,先生成xps文件,然后将文件读取出来以后,合并成一个文件来处理。
如果要是直接先打开一个xps文件,用新文件去写FixedDocument,或者DocumentSequence ,添加到新的文件中的话,会报错,提示,
“System.Windows.Xps.XpsPackagingException”类型的未经处理的异常在 ReachFramework.dll 中发生其他信息: Package 已经有根 DocumentSequence 或 FixedDocument。“
如果你要是直接写元素的话,则出现如下提示:
”System.InvalidOperationException”类型的未经处理的异常在 PresentationFramework.dll 中发生其他信息: 指定的元素已经是另一个元素的逻辑子元素。请先将其断开连接。“
通过研究微软的一个例子,终于搞定:
如果您技术超强,可以直接去看微软的例子,那个上面定义了5个类,有预览、显示、文件拖动,异步读取等等,非常的全的确是一个好例子,也比较适合于学习如何定义类,但是很容易被里面的东西给绕晕了,我比照的这个例子自己写了一个简单的合并文件的函数,可以比较直观的了解xps的结构,复制的情况。
上代码:
1 private void Button_Click(object sender, RoutedEventArgs e) 2 { 3 MergeDocument(); 4 5 } 6 7 //完全不使用类,函数方式 8 public void MergeDocument() 9 { 10 11 string fristFile = "test1.xps"; 12 string secoFile = "test2.xps"; 13 14 string newFile = "xpsShow.xps"; 15 File.Delete(newFile); 16 17 18 FixedDocumentSequence newFds = new FixedDocumentSequence();//创建一个新的文档结构 19 20 DocumentReference newDocRef = AddPage(fristFile);//加入第一个文件 21 newFds.References.Add(newDocRef); 22 23 newDocRef = AddPage(secoFile); 24 newFds.References.Add(newDocRef);//加入第二个文件 25 26 //xps写入新文件 27 XpsDocument NewXpsDocument = new XpsDocument(newFile, System.IO.FileAccess.ReadWrite); 28 XpsDocumentWriter xpsDocumentWriter = XpsDocument.CreateXpsDocumentWriter(NewXpsDocument); 29 xpsDocumentWriter.Write(newFds); 30 NewXpsDocument.Close(); 31 32 //读取并显示 33 XpsDocument xpsnewDocument = new XpsDocument(newFile, FileAccess.Read); 34 docView.Document = xpsnewDocument.GetFixedDocumentSequence(); 35 } 36 37 public DocumentReference AddPage(string fileName) 38 { 39 DocumentReference newDocRef = new DocumentReference(); 40 FixedDocument newFd = new FixedDocument(); 41 42 XpsDocument xpsDocument = new XpsDocument(fileName, FileAccess.Read); 43 FixedDocumentSequence docSeq = xpsDocument.GetFixedDocumentSequence(); 44 45 foreach (DocumentReference docRef in docSeq.References) 46 { 47 FixedDocument fd = docRef.GetDocument(false); 48 49 foreach (PageContent oldPC in fd.Pages) 50 { 51 Uri uSource = oldPC.Source;//读取源地址 52 Uri uBase = (oldPC as IUriContext).BaseUri;//读取目标页面地址 53 54 PageContent newPageContent = new PageContent(); 55 newPageContent.GetPageRoot(false);//这个地方应当是把文档解压成一个包放到内存中我们再去读取 56 newPageContent.Source = uSource; 57 (newPageContent as IUriContext).BaseUri = uBase; 58 newFd.Pages.Add(newPageContent);//将新文档追加到新的documentRefences中 59 } 60 } 61 newDocRef.SetDocument(newFd); 62 xpsDocument.Close(); 63 return newDocRef; 64 }
在这个例子中,xps文档是通过页面的方式直接读取了以后复制的。
xps文档真是一个好东西,我个人认为,我们完全可以将xps文档做成一个简单的报表打印工具,尤其适合哪种用户要求格式严格、数据项目比较多,打印要求不能有锯齿的表格打印(计算不是他的强项)。