2008-12-09 22 views
17

Me gustaría crear un documento XPS para almacenar e imprimir.¿Cómo crear un documento XPS?

¿Cuál es la forma más fácil de crear un documento XPS (por ejemplo, con una cuadrícula simple con algunos datos dentro) en mi programa, y ​​pasarlo?

+0

Esto también podría ayudar: [http://blogs.msdn.com/fyuan/archive/2005/09/12/463887.aspx](http://blogs.msdn.com/fyuan/archive/2005/ 09/12/463887.aspx) – noesgard

Respuesta

11

nada fácil en él. Pero puede hacerse. Tengo algunos (por desgracia, aún con errores) código de muestra e información en mi blog para crear el documento en la memoria.

Aquí hay un código que preparé para las pruebas que encapsula todo (escribe una colección de páginas fijas en un documento XPS en la memoria). Incluye código para serializar el documento en una matriz de bytes, pero se puede omitir esa parte y simplemente devolver el documento:

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

Nota del código enhebrado de mierda. No puedes hacer esto en los hilos de MTA; si estás en un hilo STA, puedes deshacerte de eso también.

+1

Código de tiempo de espera de subprocesos interesante - ¿Alguna razón por la que no utilizó simplemente t.Join (5000) en su lugar? Todavía estoy tratando de comprender el resto :) – Sam

+2

Su código de prueba de mierda, ¿qué puedo decir? – Will

+0

¿Compilará/trabajará este código en .NET 4? Veo la variable "escritor" definida dos veces en el mismo ámbito, y se accederá a los elementos de la colección FixedPage desde un hilo diferente al que se crearon. – Michael

-1

Todo lo que es, es realmente XML. Si se siente cómodo trabajando con archivos XML, no debería tener problemas para trabajar con documentos XPS. He aquí un sencillo tutorial que he utilizado en el pasado para me refiero a:

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

+0

Bizarre. Pero definitivamente una forma en que puedes hacerlo. No recomendaría hacerlo de esta manera a menos que haya entendido las especificaciones del documento XPS. – Will

+0

¿Creando un documento XML extraño, comprimido en un zip? No era exactamente lo que tenía en mente cuando escribí 'la manera más fácil' :) – Sam

4

Si está trabajando en .NET (v2 o posterior), puede generar muy fácilmente un documento XPS válido desde un visualizador WPF.

Por ejemplo, echar un vistazo a esta entrada del blog mío:

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

En el ejemplo creo un WPF visual y convertirlo en un archivo XPS, antes de hacer su posterior procesamiento.

Si no está trabajando en .NET, o quiere más control en la salida de XPS, le aconsejo que use una biblioteca (como NiXPS SDK) para esto. Es mucho más fácil de codificar y mucho menos propenso a errores que escribir las construcciones XML usted mismo (y hacer una gestión de recursos adecuada, etc.).

+1

El enlace a tu blog no funciona, ¿tal vez puedes copiar el ejemplo del código en tu respuesta? – Sam

+0

Copie y pegue la URL en lugar de seguirla, solo es la href incorrecta. Muestra perfectamente cómo crear un archivo XPS desde un visual WPF. –

+0

WPF (Windows Presentation Foundation) no se lanzó hasta .NET Framework 3.0 (con Windows Vista) –

Cuestiones relacionadas