2008-12-09 138 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結構(並進行適當的資源管理等)要少得多。