2008-12-09 28 views
17

Tôi muốn tạo một tài liệu XPS để lưu trữ và in.Cách tạo tài liệu XPS?

Cách dễ nhất để tạo một tài liệu XPS (ví dụ với một lưới đơn giản với một số dữ liệu bên trong) trong chương trình của tôi là gì, và để vượt qua nó?

+0

Điều này cũng có thể hữu ích: [http://blogs.msdn.com/fyuan/archive/2005/09/12/463887.aspx](http://blogs.msdn.com/fyuan/archive/2005/ 09/12/463887.aspx) – noesgard

Trả lời

11

Không có gì dễ dàng về nó. Nhưng nó có thể được thực hiện. Tôi có một số mã mẫu và thông tin đáng tiếc (buồn bã, vẫn còn lỗi) trên blog của tôi để tạo tài liệu trong bộ nhớ.

Dưới đây là một số mã tôi đã chọn để kiểm tra gói gọn mọi thứ (nó ghi một tập hợp FixedPages vào một tài liệu XPS trong bộ nhớ). Nó bao gồm mã để tuần tự hóa tài liệu thành một mảng byte, nhưng bạn có thể bỏ qua phần đó và chỉ trả lại tài liệu:

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; 
} 

Lưu ý mã luồng crappy. Bạn không thể làm điều này trên các chủ đề MTA; nếu bạn đang ở trên một chủ đề STA, bạn có thể loại bỏ điều đó.

+1

Mã thời gian chờ của chuỗi thú vị - bất kỳ lý do nào bạn không chỉ sử dụng t.Join (5000) thay thế? Tôi vẫn đang cố gắng để hiểu phần còn lại :) – Sam

+2

Mã thử nghiệm crappy của nó, tôi có thể nói gì? – Will

+0

Mã này sẽ biên dịch/làm việc trong .NET 4? Tôi thấy biến "writer" được định nghĩa hai lần trong cùng một phạm vi, và các mục trong bộ sưu tập FixedPage sẽ được truy cập từ một luồng khác với luồng mà chúng được tạo ra. – Michael

-1

Tất cả, thực sự là XML. Nếu bạn cảm thấy thoải mái khi làm việc với các tệp XML, bạn sẽ không gặp vấn đề gì khi làm việc với các tài liệu XPS. Dưới đây là một hướng dẫn đơn giản, tôi đã sử dụng trong quá khứ để làm cho tôi bắt đầu:

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

+0

Kỳ lạ. Nhưng chắc chắn một cách bạn có thể làm điều đó. Tôi sẽ không đề nghị làm theo cách này trừ khi bạn hiểu các đặc tả tài liệu XPS. – Will

+0

Tạo một tài liệu XML kỳ quái, được nén thành một zip? Không chính xác những gì tôi nghĩ đến khi tôi viết 'cách dễ nhất' :) – Sam

4

Nếu bạn đang làm việc trong .NET (v2 hoặc mới hơn), bạn có thể dễ dàng tạo một tài liệu XPS hợp lệ từ một hình ảnh WPF.

Đối với một ví dụ, hãy nhìn vào bài đăng blog của tôi:

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

Trong ví dụ này tôi tạo ra một WPF hình ảnh và chuyển đổi nó như một tập tin XPS, trước khi thực hiện tiếp tục xử lý.

Nếu bạn không làm việc trong .NET, hoặc muốn kiểm soát nhiều hơn đối với đầu ra XPS, thì tôi khuyên bạn nên sử dụng thư viện (như NiXPS SDK) cho việc này. Nó dễ dàng hơn rất nhiều để viết mã, và ít lỗi hơn rất nhiều so với việc viết ra các cấu trúc XML cho chính bạn (và thực hiện quản lý tài nguyên thích hợp, v.v ...).

+1

Liên kết tới blog của bạn không hoạt động, có thể bạn có thể sao chép ví dụ mã trong câu trả lời của mình thay thế? – Sam

+0

Sao chép và dán URL thay vì theo dõi nó, nó chỉ là href sai. Nó cho thấy cách hoàn hảo để tạo một tệp XPS từ một hình ảnh WPF. –

+0

WPF (Windows Presentation Foundation) đã không được phát hành cho đến khi .NET Framework 3.0 (với Windows Vista) –

Các vấn đề liên quan