Come stampare l’anteprima quando si usa un DocumentPaginator per stampare?

Sto utilizzando una class derivata da DocumentPaginator (vedi sotto) per stampare report semplici (solo testo) da un’applicazione WPF. Ce l’ho in modo che tutto venga stampato correttamente, ma come faccio a fare un’anteprima di stampa prima di stampare? Ho la sensazione che ho bisogno di usare un DocumentViewer ma non riesco a capire come.

Ecco la mia class Paginator:

public class RowPaginator : DocumentPaginator { private int rows; private Size pageSize; private int rowsPerPage; public RowPaginator(int rows) { this.rows = rows; } public override DocumentPage GetPage(int pageNumber) { int currentRow = rowsPerPage * pageNumber; int rowsToPrint = Math.Min(rowsPerPage, rows - (rowsPerPage * pageNumber - 1)); var page = new PageElementRenderer(pageNumber + 1, PageCount, currentRow, rowsToPrint) { Width = PageSize.Width, Height = PageSize.Height }; page.Measure(PageSize); page.Arrange(new Rect(new Point(0, 0), PageSize)); return new DocumentPage(page); } public override bool IsPageCountValid { get { return true; } } public override int PageCount { get { return (int)Math.Ceiling(this.rows / (double)this.rowsPerPage); } } public override Size PageSize { get { return this.pageSize; } set { this.pageSize = value; this.rowsPerPage = PageElementRenderer.RowsPerPage(this.pageSize.Height); if (rowsPerPage <= 0) throw new InvalidOperationException("Page can't fit any rows!"); } } public override IDocumentPaginatorSource Source { get { return null; } } } 

PageElementRenderer è solo un semplice UserControl che visualizza i dati (al momento solo un elenco di righe).

Ecco come uso il Pagatore di righe

 PrintDialog dialog = new PrintDialog(); if (dialog.ShowDialog() == true) { var paginator = new RowPaginator(rowsToPrint) { PageSize = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight) }; dialog.PrintDocument(paginator, "Rows Document"); } 

Ci scusiamo per il dump del codice, ma non volevo perdere qualcosa di rilevante.

Quindi ho funzionato dopo aver letto Pro WPF in C # 2008 (Pagina 726).

Fondamentalmente la class DocumentViewer ha bisogno di un file XPS per presentare un’anteprima di stampa. Quindi faccio quanto segue:

 PrintDialog dialog = new PrintDialog(); var paginator = new RowPaginator(rowsToPrint) { PageSize = new Size(dialog.PrintableAreaWidth, dialog.PrintableAreaHeight) }; string tempFileName = System.IO.Path.GetTempFileName(); //GetTempFileName creates a file, the XpsDocument throws an exception if the file already //exists, so delete it. Possible race condition if someone else calls GetTempFileName File.Delete(tempFileName); using (XpsDocument xpsDocument = new XpsDocument(tempFileName, FileAccess.ReadWrite)) { XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument); writer.Write(paginator); PrintPreview previewWindow = new PrintPreview { Owner = this, Document = xpsDocument.GetFixedDocumentSequence() }; previewWindow.ShowDialog(); } 

Sto creando la finestra di dialogo di stampa per ottenere la dimensione della pagina predefinita. C’è probabilmente un modo migliore per farlo. XpsDocument è in ReachFramework.dll (Namespace System.Windows.Xps.Packaging);

Ecco la finestra PrintPreview.

      

Il codice dietro ha solo una proprietà Document in questo modo:

 public IDocumentPaginatorSource Document { get { return viewer.Document; } set { viewer.Document = value; } } 

Il seguente codice utilizza un MemoryStream per eseguire un’anteprima di stampa.

 MemoryStream stream = new MemoryStream(); Package package = Package.Open(stream, FileMode.Create, FileAccess.ReadWrite); var uri = new Uri(@"memorystream://myXps.xps"); PackageStore.AddPackage(uri, package); var xpsDoc = new XpsDocument(package); xpsDoc.Uri = uri; XpsDocument.CreateXpsDocumentWriter(xpsDoc).Write(paginator); documentViewer.Document = xpsDoc.GetFixedDocumentSequence(); 

Ricordarsi di usare close () e rimuovere il pacchetto da PackageStore quando l’anteprima di stampa viene chiusa.

WPF non ha alcuna funzionalità di anteprima di stampa incorporata, se vuoi fare un’anteprima di stampa, devi costruirla tu stesso. Fortunatamente, non dovrebbe essere così difficile.

Hai già ottenuto il codice di impaginazione, che crea gli oggetti di DocumentPage . Questi oggetti contengono una Visual , che puoi andare avanti e visualizzare nella tua interfaccia utente.

Quello che finirai per fare, è impaginare l’intero documento, raccogliere tutti gli oggetti di DocumentPage , quindi visualizzare le loro immagini all’interno di uno StackPanel scorrevole o qualcosa di simile. Questi sono gli stessi oggetti di DocumentPage che è ansible inviare alla stampante.

Il codice WinForm per l’anteprima di stampa è:

 PrintPreviewDialog PrintPreviewDialog = new PrintPreviewDialog(); PrintPreviewDialog.Document = PrintDocument; PrintPreviewDialog.ShowDialog(); 

Ps: il poster originale ha commentato che questa è la risposta sbagliata per un’applicazione WPF.

 XpsDocument doc = new XpsDocument("filename.xps", FileAccess.Read); docViewer.Document = doc.GetFixedDocumentSequence(); doc.Close(); 

Non penso che ci sia un modo per farlo

Ecco come ho funzionato in NHaml

 var documentViewHostDialog = new DocumentDialog(); documentViewHostDialog.LoadDocument(load); documentViewHostDialog.ShowDialog(); 

Dove “load” è o FlowDocument o IDocumentPaginatorSource e qui è il http://code.google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml codice http: // DocumentDialog . google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml.cs

Spero che funzioni per il tuo caso.