2008-12-09 101 views
17

我想创建一个用于存储和打印的XPS文档。如何创建XPS文档?

在我的程序中创建XPS文档的最简单方法是什么(例如用一个简单的网格,里面有一些数据)并传递它?

+0

这可能也有帮助:[http://blogs.msdn.com/fyuan/archive/2005/09/12/463887.aspx](http://blogs.msdn.com/fyuan/archive/2005/ 09/12/463887.aspx) – noesgard 2008-12-11 09:29:56

回答

11

什么都不轻松一下吧。但这是可以完成的。我在我的博客上有一些(可惜的是,仍然是越野车)示例代码和信息,用于在内存中创建文档。

下面是我为测试所掀起的一些代码,它封装了所有内容(它将FixedPages的集合写入内存中的XPS文档)。它包括文档序列化到一个字节数组的代码,但你可以跳过这一部分,只是返回文档:

public static byte[] ToXpsDocument(IEnumerable<FixedPage> pages) 
{ 
    // 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线程上,你也可以摆脱它。

+1

有趣的线程超时代码 - 任何你没有使用t.Join(5000)的理由? 我仍然试图理解其他:) – Sam 2008-12-09 12:30:54

-1

全部是,真的是XML。如果您愿意使用XML文件,那么在使用XPS文档时应该没有问题。这里有一个简单的教程中,我已经在过去用来让我开始:

http://blogs.ocrasoft.nl/jeroenveurink/?p=21

+0

奇怪。但绝对是你能做到的一种方式。除非您了解XPS文档规范,否则我不会建议这样做。 – Will 2008-12-09 12:15:50

+0

创建一个奇怪的XML文档,压缩成一个zip文件? 当我写'最简单的方式'时,我并不完全记得:) :) – Sam 2008-12-09 12:24:33

4

如果您使用的是.NET(v2或更高版本),则可以非常方便地从WPF视觉效果中生成有效的XPS文档。

举一个例子,来看看我的这个博客帖子:

http://nixps.blogspot.com/2008/12/wpf-to-pdf.html

在这个例子中,我创建一个WPF视觉并将其转换为XPS文件,做进一步的处理之前。

如果你不是在.NET中工作,或者想要更多地控制XPS输出,那么我建议你使用一个库(如NiXPS SDK)。编写代码要容易得多,而且比自己编写XML结构(并进行适当的资源管理等)要少得多。