Printing documents overview (WPF .NET)

With Microsoft .NET, application developers using Windows Presentation Foundation (WPF) have a rich set of printing and print system management APIs. The core of this functionality is the XML Paper Specification (XPS) file format and the XPS print path.

About XPS

XPS is an electronic document format, a spool file format, and a page description language. It's an open document format that uses XML, Open Packaging Conventions, and other industry standards to create cross-platform documents. XPS simplifies the process by which digital documents are created, shared, printed, viewed, and archived. For more on XPS, see XPS Documents.

XPS print path

The XPS print path is a Windows feature that redefines how printing is handled in Windows applications. XPS print path can replace:

  • Document presentation languages, such as Rich Text Format or Portable Document Format.
  • Print spooler formats, such as Windows Metafile or Enhanced Metafile (EMF).
  • Page description languages, such as Printer Command Language or PostScript.

As a result, the XPS print path maintains the XPS format from application publication down to final processing in the printer driver or device.

The print spooler for XPS documents supports both the XPS print path and the GDI print path. The XPS print path natively consumes an XPS spool file and requires an XPS printer driver. The XPS print path is built on the XPS printer driver (XPSDrv) model.

The benefits of the XPS print path include:

  • WYSIWYG print support.
  • Native support of advanced color profiles, such as 32 bits per channel, the CMYK color model, named-colors, n-inks, and transparencies and gradients.
  • Improved print performance—XPS features and enhancements are only available to applications that target the XPS print path.
  • Industry standard XPS format.

For basic print scenarios, a simple and intuitive API is available with a standard UI for print configuration and job submission. For advanced scenarios, the API supports UI customization or no UI at all, synchronous or asynchronous printing, and batch printing capabilities. Both simple and advanced options provide print support in full or partial trust modes.

XPS was designed with extensibility in mind, so features and capabilities can be added to XPS in a modular manner. Extensibility features include:

  • A print schema that supports rapid extension of device capabilities. The public portion of the schema is regularly updated to add desired device capabilities. For more information, see Extensible architecture.
  • An extensible filter pipeline that XPSDrv drivers use to support both direct and scalable printing of XPS documents. For more information, see XPSDrv printer drivers.

WPF applications natively support the XPS print path, and can use XPS print APIs to print directly to the XPSDrv driver. If the target print queue of the write operation doesn't have an XPSDrv driver, then the Write and WriteAsync methods of the XpsDocumentWriter class will automatically convert content from XPS to GDI format, for the GDI print path.

The following illustration shows the print subsystem and defines the portions provided by Microsoft and independent software and hardware vendors.

Screenshot showing the XPS print system.

Basic XPS printing

WPF has a printing API that supports both basic and advanced printing features. For those applications that don't require extensive print customization or access to the complete XPS feature set, basic print support might suffice. Basic print support is provided through a PrintDialog control that requires minimal configuration, has a familiar UI, and supports many XPS features.

PrintDialog

The System.Windows.Controls.PrintDialog control provides a single entry point for UI, configuration, and XPS job submission. To learn how to instantiate and use the control, see How to display a print dialog.

Advanced XPS printing

To access the complete set of XPS features, use the advanced printing API. Several relevant APIs are described in this section, including PrintTicket, PrintCapabilities, PrintServer, PrintQueue, and XpsDocumentWriter. For a complete list of XPS print path APIs, see the System.Windows.Xps and System.Printing namespaces.

PrintTicket and PrintCapabilities

The PrintTicket and PrintCapabilities classes are the foundation of advanced XPS features. Both objects contain XML formatted structures of print-oriented features that are defined by the print schema. The features include duplexing, collation, two-sided printing, and stapling. A PrintTicket instructs a printer how to process a print job. The PrintCapabilities class defines the capabilities of a printer. By querying the capabilities of a printer, a PrintTicket can be created that takes full advantage of a printer's supported features. Similarly, unsupported features can be avoided.

The following example queries the PrintCapabilities of a printer and creates a PrintTicket using code.

/// <summary>
/// Returns a print ticket, which is a set of instructions telling a printer how
/// to set its various features, such as duplexing, collating, and stapling.
/// </summary>
/// <param name="printQueue">The print queue to print to.</param>
/// <returns>A print ticket.</returns>
public static PrintTicket GetPrintTicket(PrintQueue printQueue)
{
    PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();

    // Get a default print ticket from printer.
    PrintTicket printTicket = printQueue.DefaultPrintTicket;

    // Modify the print ticket.
    if (printCapabilites.CollationCapability.Contains(Collation.Collated))
        printTicket.Collation = Collation.Collated;
    if (printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge))
        printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
    if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
        printTicket.Stapling = Stapling.StapleDualLeft;

    // Returns a print ticket, which is a set of instructions telling a printer how
    // to set its various features, such as duplexing, collating, and stapling.
    return printTicket;
}
''' <summary>
''' Returns a print ticket, which is a set of instructions telling a printer how
''' to set its various features, such as duplexing, collating, and stapling.
''' </summary>
''' <param name="printQueue">The print queue to print to.</param>
''' <returns>A print ticket.</returns>
Public Shared Function GetPrintTicket(printQueue As PrintQueue) As PrintTicket

    Dim printCapabilites As PrintCapabilities = printQueue.GetPrintCapabilities()

    ' Get a default print ticket from printer.
    Dim printTicket As PrintTicket = printQueue.DefaultPrintTicket

    ' Modify the print ticket.
    If printCapabilites.CollationCapability.Contains(Collation.Collated) Then
        printTicket.Collation = Collation.Collated
    End If
    If printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
        printTicket.Duplexing = Duplexing.TwoSidedLongEdge
    End If
    If printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
        printTicket.Stapling = Stapling.StapleDualLeft
    End If

    ' Returns a print ticket, which is a set of instructions telling a printer how
    ' to set its various features, such as duplexing, collating, and stapling.
    Return printTicket

End Function

PrintServer and PrintQueue

The PrintServer class represents a network print server, and the PrintQueue class represents a printer and the output job queue associated with it. Together, these APIs support advanced management of the print jobs for a server. A PrintServer, or one of its derived classes, is used to manage a PrintQueue.

The following example creates a LocalPrintServer and accesses the local computer's PrintQueueCollection using code.

/// <summary>
/// Return a collection of print queues, which individually hold the features or states
/// of a printer as well as common properties for all print queues.
/// </summary>
/// <returns>A collection of print queues.</returns>
public static PrintQueueCollection GetPrintQueues()
{
    // Create a LocalPrintServer instance, which represents 
    // the print server for the local computer.
    LocalPrintServer localPrintServer = new();

    // Get the default print queue on the local computer.
    //PrintQueue printQueue = localPrintServer.DefaultPrintQueue;

    // Get all print queues on the local computer.
    PrintQueueCollection printQueueCollection = localPrintServer.GetPrintQueues();

    // Return a collection of print queues, which individually hold the features or states
    // of a printer as well as common properties for all print queues.
    return printQueueCollection;
}
''' <summary>
''' Return a collection of print queues, which individually hold the features or states
''' of a printer as well as common properties for all print queues.
''' </summary>
''' <returns>A collection of print queues.</returns>
Public Shared Function GetPrintQueues() As PrintQueueCollection

    ' Create a LocalPrintServer instance, which represents 
    ' the print server for the local computer.
    Dim localPrintServer As LocalPrintServer = New LocalPrintServer()

    ' Get the default print queue on the local computer.
    'Dim  printQueue As PrintQueue = localPrintServer.DefaultPrintQueue

    ' Get all print queues on the local computer.
    Dim printQueueCollection As PrintQueueCollection = localPrintServer.GetPrintQueues()

    ' Return a collection of print queues, which individually hold the features or states
    ' of a printer as well as common properties for all print queues.
    Return printQueueCollection

End Function

XpsDocumentWriter

XpsDocumentWriter, with its many Write and WriteAsync methods, is used to add XPS documents to a PrintQueue. For example, the Write(FixedDocumentSequence, PrintTicket) method is used to synchronously add an XPS document with a print ticket to a queue. The WriteAsync(FixedDocumentSequence, PrintTicket) method is used to asynchronously add an XPS document with a print ticket to a queue.

The following example creates an XpsDocumentWriter and adds XPS documents, both synchronously and asynchronously, to a PrintQueue using code.

/// <summary>
/// Asynchronously, add the XPS document together with a print ticket to the print queue.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file.</param>
/// <param name="printQueue">The print queue to print to.</param>
/// <param name="printTicket">The print ticket for the selected print queue.</param>
public static void PrintXpsDocumentAsync(string xpsFilePath, PrintQueue printQueue, PrintTicket printTicket)
{
    // Create an XpsDocumentWriter object for the print queue.
    XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);

    // Open the selected document.
    XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);

    // Get a fixed document sequence for the selected document.
    FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();

    // Asynchronously, add the XPS document together with a print ticket to the print queue.
    xpsDocumentWriter.WriteAsync(fixedDocSeq, printTicket);
}

/// <summary>
/// Synchronously, add the XPS document together with a print ticket to the print queue.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file.</param>
/// <param name="printQueue">The print queue to print to.</param>
/// <param name="printTicket">The print ticket for the selected print queue.</param>
public static void PrintXpsDocument(string xpsFilePath, PrintQueue printQueue, PrintTicket printTicket)
{
    // Create an XpsDocumentWriter object for the print queue.
    XpsDocumentWriter xpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue);

    // Open the selected document.
    XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);

    // Get a fixed document sequence for the selected document.
    FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();

    // Synchronously, add the XPS document together with a print ticket to the print queue.
    xpsDocumentWriter.Write(fixedDocSeq, printTicket);
}
''' <summary>
''' Asynchronously, add the XPS document together with a print ticket to the print queue.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file.</param>
''' <param name="printQueue">The print queue to print to.</param>
''' <param name="printTicket">The print ticket for the selected print queue.</param>
Public Shared Sub PrintXpsDocumentAsync(xpsFilePath As String, printQueue As PrintQueue, printTicket As PrintTicket)

    ' Create an XpsDocumentWriter object for the print queue.
    Dim xpsDocumentWriter As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue)

    ' Open the selected document.
    Dim xpsDocument As XpsDocument = New XpsDocument(xpsFilePath, FileAccess.Read)

    ' Get a fixed document sequence for the selected document.
    Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()

    ' Asynchronously, add the XPS document together with a print ticket to the print queue.
    xpsDocumentWriter.WriteAsync(fixedDocSeq, printTicket)

End Sub

''' <summary>
''' Synchronously, add the XPS document together with a print ticket to the print queue.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file.</param>
''' <param name="printQueue">The print queue to print to.</param>
''' <param name="printTicket">The print ticket for the selected print queue.</param>
Public Shared Sub PrintXpsDocument(xpsFilePath As String, printQueue As PrintQueue, printTicket As PrintTicket)

    ' Create an XpsDocumentWriter object for the print queue.
    Dim xpsDocumentWriter As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(printQueue)

    ' Open the selected document.
    Dim xpsDocument As XpsDocument = New XpsDocument(xpsFilePath, FileAccess.Read)

    ' Get a fixed document sequence for the selected document.
    Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()

    ' Synchronously, add the XPS document together with a print ticket to the print queue.
    xpsDocumentWriter.Write(fixedDocSeq, printTicket)

End Sub

GDI print path

Although WPF applications natively support the XPS print path, they can also output to the GDI print path by calling one of the Write or WriteAsync methods of the XpsDocumentWriter class and selecting the print queue for a non-XpsDrv printer.

For applications that don't require XPS functionality or support, the current GDI print path remains unchanged. For more about the GDI print path and the various XPS conversion options, see Microsoft XPS document converter (MXDC) and XPSDrv printer drivers.

XPSDrv driver model

The XPS print path improves spooler efficiency by using XPS as the native print spool format when printing to an XPS-enabled printer or driver. Unlike EMF, which represents application output as a series of calls into GDI for rendering services, XPS spool format represents the document. So, when XPS spool files are output to an XPS-based printer driver, they don't require further interpretation as the drivers operate directly on data in that format. This capability eliminates the data and color space conversions required for EMF files and GDI-based print drivers.

The simplified spooling process eliminates the need to generate an intermediate spool file, such as an EMF data file, before the document is spooled. With smaller spool file sizes, the XPS print path can reduce network traffic and improve print performance. Compared with their EMF equivalents, XPS spool file sizes are typically reduced when using the XPS print path. Spool file size reduction is done through several mechanisms:

  • Font subsetting, which only stores the characters used within a document in the XPS file.
  • Advanced graphics support, which natively supports transparency and gradient primitives to avoid rasterization of XPS content.
  • Identification of common resources, such as an image of a corporate logo that's used multiple times in a document. Common resources are treated as shared resources and are only loaded once.
  • ZIP compression, which is used on all XPS documents.

The XPS spool file size might not be reduced if a vector graphic is highly complex, multi-layered, or inefficiently written. Unlike GDI spool files, XPS files embed device fonts and computer-based fonts for screen display purposes, though both kinds of fonts are subsetted and printer drivers can remove device fonts before transmitting the file to the printer.

Tip

You can also print XPS files by using PrintQueue.AddJob methods. For more information, see How to print XPS files.

See also