Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
¿Desea imprimir desde la aplicación? Puede usar la PrintDialog clase para abrir un cuadro de diálogo de impresión estándar de Microsoft Windows. Así es como.
Nota:
El System.Windows.Controls.PrintDialog control usado para WPF y que se describe aquí no debe confundirse con el System.Windows.Forms.PrintDialog componente de Windows Forms.
La PrintDialog clase proporciona un único control para la configuración de impresión y el envío de trabajos de impresión. El control es fácil de usar y puede instanciarse mediante el marcado XAML o el código. En los ejemplos siguientes se crea y se muestra una PrintDialog
instancia mediante código.
Puede usar el cuadro de diálogo de impresión para configurar las opciones de impresión, como:
- Imprima solo un intervalo específico de páginas.
- Seleccione entre impresoras instaladas en el equipo. Puede usar la opción Escritor de documentos de Microsoft XPS para crear estos tipos de documento:
- Especificación de papel XML (XPS)
- Especificación de papel Open XML (OpenXPS)
Imprimir todo el documento
En este ejemplo se imprimen todas las páginas de un documento XPS. De forma predeterminada, el código hará lo siguiente:
- Abra una ventana de diálogo de impresión que pida al usuario que seleccione una impresora e inicie un trabajo de impresión.
- Crea una instancia de un objeto XpsDocument con el contenido del documento XPS.
- Utilice el
XpsDocument
objeto para generar un DocumentPaginator objeto que contenga todas las páginas del documento XPS. - Llame al método PrintDocument, pasando el objeto
DocumentPaginator
, para enviar todas las páginas a la impresora especificada.
/// <summary>
/// Print all pages of an XPS document.
/// Optionally, hide the print dialog window.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file</param>
/// <param name="hidePrintDialog">Whether to hide the print dialog window (shown by default)</param>
/// <returns>Whether the document printed</returns>
public static bool PrintWholeDocument(string xpsFilePath, bool hidePrintDialog = false)
{
// Create the print dialog object and set options.
PrintDialog printDialog = new();
if (!hidePrintDialog)
{
// Display the dialog. This returns true if the user presses the Print button.
bool? isPrinted = printDialog.ShowDialog();
if (isPrinted != true)
return false;
}
// Print the whole document.
try
{
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Create a paginator for all pages in the selected document.
DocumentPaginator docPaginator = fixedDocSeq.DocumentPaginator;
// Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}");
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
}
''' <summary>
''' Print all pages of an XPS document.
''' Optionally, print all pages without showing a print dialog window.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file</param>
''' <param name="hidePrintDialog">Whether to hide the print dialog window (shown by default)</param>
''' <returns>Whether the document printed</returns>
Public Shared Function PrintWholeDocument(xpsFilePath As String, Optional hidePrintDialog As Boolean = False) As Boolean
' Create the print dialog object and set options.
Dim printDialog As New PrintDialog
If Not hidePrintDialog Then
' Display the dialog. This returns true if the user presses the Print button.
Dim isPrinted As Boolean? = printDialog.ShowDialog()
If isPrinted <> True Then Return False
End If
' Print the whole document.
Try
' Open the selected document.
Dim xpsDocument As New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Create a paginator for all pages in the selected document.
Dim docPaginator As DocumentPaginator = fixedDocSeq.DocumentPaginator
' Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}")
Return True
Catch e As Exception
MessageBox.Show(e.Message)
Return False
End Try
End Function
Imprimir un intervalo de páginas
A veces solo querrá imprimir un intervalo específico de páginas dentro de un documento XPS. Para ello, ampliamos la clase abstracta DocumentPaginator para agregar compatibilidad con intervalos de páginas. De forma predeterminada, el código hará lo siguiente:
- Abra una ventana de diálogo de impresión que pida al usuario que seleccione una impresora, especifique un intervalo de páginas e inicie un trabajo de impresión.
- Crea una instancia de un objeto XpsDocument con el contenido del documento XPS.
- Utilice el
XpsDocument
objeto para generar un objeto predeterminado DocumentPaginator que contenga todas las páginas del documento XPS. - Cree una instancia de una clase
DocumentPaginator
extendida que admita intervalos de páginas, pasando el objeto predeterminadoDocumentPaginator
y la estructura PageRange devuelta por PrintDialog. - Llame al método PrintDocument, pasando la instancia de la clase
DocumentPaginator
extendida, para enviar el intervalo de páginas especificado a la impresora especificada.
/// <summary>
/// Print a specific range of pages within an XPS document.
/// </summary>
/// <param name="xpsFilePath">Path to source XPS file</param>
/// <returns>Whether the document printed</returns>
public static bool PrintDocumentPageRange(string xpsFilePath)
{
// Create the print dialog object and set options.
PrintDialog printDialog = new()
{
UserPageRangeEnabled = true
};
// Display the dialog. This returns true if the user presses the Print button.
bool? isPrinted = printDialog.ShowDialog();
if (isPrinted != true)
return false;
// Print a specific page range within the document.
try
{
// Open the selected document.
XpsDocument xpsDocument = new(xpsFilePath, FileAccess.Read);
// Get a fixed document sequence for the selected document.
FixedDocumentSequence fixedDocSeq = xpsDocument.GetFixedDocumentSequence();
// Create a paginator for all pages in the selected document.
DocumentPaginator docPaginator = fixedDocSeq.DocumentPaginator;
// Check whether a page range was specified in the print dialog.
if (printDialog.PageRangeSelection == PageRangeSelection.UserPages)
{
// Create a document paginator for the specified range of pages.
docPaginator = new DocPaginator(fixedDocSeq.DocumentPaginator, printDialog.PageRange);
}
// Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}");
return true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return false;
}
}
/// <summary>
/// Extend the abstract DocumentPaginator class to support page range printing. This class is based on the following online resources:
///
/// https://www.thomasclaudiushuber.com/2009/11/24/wpf-printing-how-to-print-a-pagerange-with-wpfs-printdialog-that-means-the-user-can-select-specific-pages-and-only-these-pages-are-printed/
///
/// https://social.msdn.microsoft.com/Forums/vstudio/en-US/9180e260-0791-4f2d-962d-abcb22ba8d09/how-to-print-multiple-page-ranges-with-wpf-printdialog
///
/// https://social.msdn.microsoft.com/Forums/en-US/841e804b-9130-4476-8709-0d2854c11582/exception-quotfixedpage-cannot-contain-another-fixedpagequot-when-printing-to-the-xps-document?forum=wpf
/// </summary>
public class DocPaginator : DocumentPaginator
{
private readonly DocumentPaginator _documentPaginator;
private readonly int _startPageIndex;
private readonly int _endPageIndex;
private readonly int _pageCount;
public DocPaginator(DocumentPaginator documentPaginator, PageRange pageRange)
{
// Set document paginator.
_documentPaginator = documentPaginator;
// Set page indices.
_startPageIndex = pageRange.PageFrom - 1;
_endPageIndex = pageRange.PageTo - 1;
// Validate and set page count.
if (_startPageIndex >= 0 &&
_endPageIndex >= 0 &&
_startPageIndex <= _documentPaginator.PageCount - 1 &&
_endPageIndex <= _documentPaginator.PageCount - 1 &&
_startPageIndex <= _endPageIndex)
_pageCount = _endPageIndex - _startPageIndex + 1;
}
public override bool IsPageCountValid => true;
public override int PageCount => _pageCount;
public override IDocumentPaginatorSource Source => _documentPaginator.Source;
public override Size PageSize { get => _documentPaginator.PageSize; set => _documentPaginator.PageSize = value; }
public override DocumentPage GetPage(int pageNumber)
{
DocumentPage documentPage = _documentPaginator.GetPage(_startPageIndex + pageNumber);
// Workaround for "FixedPageInPage" exception.
if (documentPage.Visual is FixedPage fixedPage)
{
var containerVisual = new ContainerVisual();
foreach (object child in fixedPage.Children)
{
var childClone = (UIElement)child.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(child, null);
FieldInfo parentField = childClone.GetType().GetField("_parent", BindingFlags.Instance | BindingFlags.NonPublic);
if (parentField != null)
{
parentField.SetValue(childClone, null);
containerVisual.Children.Add(childClone);
}
}
return new DocumentPage(containerVisual, documentPage.Size, documentPage.BleedBox, documentPage.ContentBox);
}
return documentPage;
}
}
''' <summary>
''' Print a specific range of pages within an XPS document.
''' </summary>
''' <param name="xpsFilePath">Path to source XPS file</param>
''' <returns>Whether the document printed</returns>
Public Shared Function PrintDocumentPageRange(xpsFilePath As String) As Boolean
' Create the print dialog object and set options.
Dim printDialog As New PrintDialog With {
.UserPageRangeEnabled = True
}
' Display the dialog. This returns true if the user presses the Print button.
Dim isPrinted As Boolean? = printDialog.ShowDialog()
If isPrinted <> True Then Return False
' Print a specific page range within the document.
Try
' Open the selected document.
Dim xpsDocument As New XpsDocument(xpsFilePath, FileAccess.Read)
' Get a fixed document sequence for the selected document.
Dim fixedDocSeq As FixedDocumentSequence = xpsDocument.GetFixedDocumentSequence()
' Create a paginator for all pages in the selected document.
Dim docPaginator As DocumentPaginator = fixedDocSeq.DocumentPaginator
' Check whether a page range was specified in the print dialog.
If printDialog.PageRangeSelection = PageRangeSelection.UserPages Then
' Create a document paginator for the specified range of pages.
docPaginator = New DocPaginator(fixedDocSeq.DocumentPaginator, printDialog.PageRange)
End If
' Print to a new file.
printDialog.PrintDocument(docPaginator, $"Printing {Path.GetFileName(xpsFilePath)}")
Return True
Catch e As Exception
MessageBox.Show(e.Message)
Return False
End Try
End Function
' Extend the abstract DocumentPaginator class to support page range printing.
' This class is based on the following online resources:
' https://www.thomasclaudiushuber.com/2009/11/24/wpf-printing-how-to-print-a-pagerange-with-wpfs-printdialog-
' that-means-the-user-can-select-specific-pages-and-only-these-pages-are-printed/
' https://social.msdn.microsoft.com/Forums/vstudio/en-US/9180e260-0791-4f2d-962d-abcb22ba8d09/how-to-print-
' multiple-page-ranges-with-wpf-printdialog
' https://social.msdn.microsoft.com/Forums/en-US/841e804b-9130-4476-8709-0d2854c11582/exception-quotfixedpage-
' cannot-contain-another-fixedpagequot-when-printing-to-the-xps-document?forum=wpf
Public Class DocPaginator
Inherits DocumentPaginator
Private ReadOnly _documentPaginator As DocumentPaginator
Private ReadOnly _startPageIndex As Integer
Private ReadOnly _endPageIndex As Integer
Private ReadOnly _pageCount As Integer
Public Sub New(documentPaginator As DocumentPaginator, pageRange As PageRange)
' Set document paginator.
_documentPaginator = documentPaginator
' Set page indices.
_startPageIndex = pageRange.PageFrom - 1
_endPageIndex = pageRange.PageTo - 1
' Validate And set page count.
If _startPageIndex >= 0 AndAlso
_endPageIndex >= 0 AndAlso
_startPageIndex <= _documentPaginator.PageCount - 1 AndAlso
_endPageIndex <= _documentPaginator.PageCount - 1 AndAlso
_startPageIndex <= _endPageIndex Then
_pageCount = _endPageIndex - _startPageIndex + 1
End If
End Sub
Public Overrides ReadOnly Property IsPageCountValid As Boolean
Get
Return True
End Get
End Property
Public Overrides ReadOnly Property PageCount As Integer
Get
Return _pageCount
End Get
End Property
Public Overrides ReadOnly Property Source As IDocumentPaginatorSource
Get
Return _documentPaginator.Source
End Get
End Property
Public Overrides Property PageSize As Size
Get
Return _documentPaginator.PageSize
End Get
Set(value As Size)
_documentPaginator.PageSize = value
End Set
End Property
Public Overrides Function GetPage(pageNumber As Integer) As DocumentPage
Dim documentPage As DocumentPage = _documentPaginator.GetPage(_startPageIndex + pageNumber)
' Workaround for "FixedPageInPage" exception.
If documentPage.Visual.GetType() Is GetType(FixedPage) Then
Dim fixedPage As FixedPage = documentPage.Visual
Dim containerVisual = New ContainerVisual()
For Each child As Object In fixedPage.Children
Dim childClone = CType(child.[GetType]().GetMethod("MemberwiseClone", BindingFlags.Instance Or BindingFlags.NonPublic).Invoke(child, Nothing), UIElement)
Dim parentField As FieldInfo = childClone.[GetType]().GetField("_parent", BindingFlags.Instance Or BindingFlags.NonPublic)
If parentField IsNot Nothing Then
parentField.SetValue(childClone, Nothing)
containerVisual.Children.Add(childClone)
End If
Next
Return New DocumentPage(containerVisual, documentPage.Size, documentPage.BleedBox, documentPage.ContentBox)
End If
Return documentPage
End Function
End Class
Sugerencia
Aunque puede usar el PrintDocument método para imprimir sin abrir el cuadro de diálogo de impresión, por motivos de rendimiento, es mejor usar el AddJob método o uno de los muchos Write y WriteAsync métodos de XpsDocumentWriter. Para obtener más información sobre esto, consulte Cómo imprimir un archivo XPS e Información general sobre la impresión de documentos.
Consulte también
.NET Desktop feedback