2009-02-25 5 views
13

Ich verwende eine Klasse, die ich von DocumentPaginator (siehe unten) abgeleitet habe, um einfache (nur Text) Berichte aus einer WPF-Anwendung zu drucken. Ich habe es so, dass alles richtig druckt, Aber wie bekomme ich es, eine Druckvorschau vor dem Drucken zu machen? Ich habe das Gefühl, ich brauche einen DocumentViewer, aber ich kann nicht herausfinden, wie.Wie wird die Vorschau gedruckt, wenn ein DocumentPaginator zum Drucken verwendet wird?

Hier ist meine Paginator Klasse:

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

Die PageElementRenderer ist nur ein einfaches Benutzersteuerelement, das die Daten anzeigt (im Moment nur eine Liste von Zeilen).

Hier ist, wie ich meinen Row Paginator

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

Sorry für den Code-Dump verwenden, aber ich wollte nicht relevant, etwas verpassen.

+0

siehe auch: http://stackoverflow.com/questions/2322064/how-can-i-produce-a-print-preview-of-a-flowdocument-in-a-wpf-application – Cheeso

Antwort

17

So habe ich es nach dem Lesen Pro WPF in C# 2008 (Seite 726) funktioniert.

Grundsätzlich benötigt die DocumentViewer-Klasse eine XPS-Datei, um eine Druckvorschau davon zu präsentieren. Also mache ich folgendes:

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

Ich erstelle den Druckdialog, um die Standardseitengröße zu erhalten. Es gibt wahrscheinlich einen besseren Weg, dies zu tun. XpsDocument befindet sich in ReachFramework.dll (Namespace System.Windows.Xps.Packaging);

Hier ist das PrintPreview-Fenster.

<Window x:Class="WPFPrintTest.PrintPreview" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    x:Name="previewWindow" 
    Title="PrintPreview" Height="800" Width="800"> 
    <Grid> 
     <DocumentViewer Name="viewer" 
         Document="{Binding ElementName=previewWindow, Path=Document}" /> 
    </Grid> 
</Window> 

Der Code hinter hat nur ein Document-Eigenschaft wie folgt:

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

FYI, können Sie System.IO.Path verwenden. GetRandomFileName() (http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx) anstelle von Path.GetTempFileName(), um einen Dateinamen ohne Erstellen der Datei abzurufen. – Cheeso

1

Der WinForm-Code für Druckvorschau ist:

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

P. S .: Das ursprüngliche Plakat hat kommentiert, dass dies für eine WPF-Anwendung die falsche Antwort ist.

+0

Das ist die WinForms-Methode. – Ray

+0

Ich stehe korrigiert. :( – MrValdez

+0

Ich hoffe, dass es Ihnen nichts ausmacht, ich lasse diese Antwort hier für zukünftige Suchen auf C# und drucken. – MrValdez

0

Ich denke nicht, gibt es eine in Art und Weise, dies zu tun

Hier gebaut ist, wie ich es in NHaml Arbeit bekam

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

Wo „Last“ ist entweder ein Flowdocument oder IDocumentPaginatorSource und hier ist die DocumentDialog http://code.google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml http://code.google.com/p/nhaml/source/browse/trunk/src/NHaml.Xps/DocumentDialog.xaml.cs

Hoffe, dass es für Ihren Fall funktioniert.

3

WPF verfügt nicht über eine integrierte Druckvorschau. Wenn Sie eine Druckvorschau erstellen möchten, müssen Sie sie selbst erstellen. Zum Glück sollte es nicht so schwierig sein.

Sie haben bereits den Paginierungscode, der Ihre DocumentPage Objekte erstellt. Diese Objekte enthalten eine Visual, die Sie in Ihrer Benutzeroberfläche anzeigen können.

Was Sie tun werden, ist paginieren Ihr gesamtes Dokument, sammelt alle DocumentPage Objekte, dann ihre Visuals innerhalb einer scrollenden StackPanel oder etwas ähnliches anzeigen. Dies sind die gleichen DocumentPage Objekte, die Sie dann an den Drucker senden können.

+0

Dies ist eigentlich eine bessere Lösung als Document Viewer. Danke. –

5

Der folgende Code verwendet eine Memory eine Druckvorschau zu tun.

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(); 

Denken Sie daran, close() zu verwenden, und Paket von Packages zu entfernen, wenn die Druckvorschau geschlossen ist.

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