我想创建一个用于存储和打印的XPS文档.
在我的程序中创建XPS文档的最简单方法是什么(例如,在其中包含一些带有一些数据的简单网格),并传递它?
没什么好吃的.但这是可以完成的.我在我的博客上有一些(遗憾的,仍然是错误的)示例代码和信息,用于在内存中创建文档.
这是我为测试而编写的一些代码封装了所有内容(它将一组FixedPages写入内存中的XPS文档).它包含用于将文档序列化为字节数组的代码,但您可以跳过该部分并返回文档:
public static byte[] ToXpsDocument(IEnumerablepages) { // XPS DOCUMENTS MUST BE CREATED ON STA THREADS!!! // Note, this is test code, so I don't care about disposing my memory streams // You'll have to pay more attention to their lifespan. You might have to // serialize the xps document and remove the package from the package store // before disposing the stream in order to prevent throwing exceptions byte[] retval = null; Thread t = new Thread(new ThreadStart(() => { // A memory stream backs our document MemoryStream ms = new MemoryStream(2048); // a package contains all parts of the document Package p = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite); // the package store manages packages Uri u = new Uri("pack://TemporaryPackageUri.xps"); PackageStore.AddPackage(u, p); // the document uses our package for storage XpsDocument doc = new XpsDocument(p, CompressionOption.NotCompressed, u.AbsoluteUri); // An xps document is one or more FixedDocuments containing FixedPages FixedDocument fDoc = new FixedDocument(); PageContent pc; foreach (var fp in pages) { // this part of the framework is weak and hopefully will be fixed in 4.0 pc = new PageContent(); ((IAddChild)pc).AddChild(fp); fDoc.Pages.Add(pc); } // we use the writer to write the fixed document to the xps document XpsDocumentWriter writer; writer = XpsDocument.CreateXpsDocumentWriter(doc); // The paginator controls page breaks during the writing process // its important since xps document content does not flow writer.Write(fDoc.DocumentPaginator); // p.Flush(); // this part serializes the doc to a stream so we can get the bytes ms = new MemoryStream(); var writer = new XpsSerializerFactory().CreateSerializerWriter(ms); writer.Write(doc.GetFixedDocumentSequence()); retval = ms.ToArray(); })); // Instantiating WPF controls on a MTA thread throws exceptions t.SetApartmentState(ApartmentState.STA); // adjust as needed t.Priority = ThreadPriority.AboveNormal; t.IsBackground = false; t.Start(); //~five seconds to finish or we bail int milli = 0; while (buffer == null && milli++ < 5000) Thread.Sleep(1); //Ditch the thread if(t.IsAlive) t.Abort(); // If we time out, we return null. return retval; }
请注意糟糕的线程代码.你不能在MTA线程上这样做; 如果你在STA线程上,你也可以摆脱它.
如果您使用的是.NET(v2或更高版本),则可以从WPF visual中轻松生成有效的XPS文档.
举个例子,看一下我的博文:
http://nixps.blogspot.com/2008/12/wpf-to-pdf.html
在示例中,我创建了一个WPF visual并将其转换为XPS文件,然后再进行进一步处理.
如果您不在.NET中工作,或者想要更多地控制XPS输出,那么我建议您使用库(如NiXPS SDK).编写代码要容易得多,并且比自己编写XML构造(并进行适当的资源管理等等)更不容易出错.