Как распечатать предварительный просмотр при использовании DocumentPaginator для печати?
Я использую класс, который я получил из DocumentPaginator (см. ниже) для печати простых (только текстовых) отчетов из приложения WPF. У меня есть так, что все печатает правильно, Но как мне заставить его делать предварительный просмотр перед печатью? У меня есть ощущение, что мне нужно использовать DocumentViewer, но я не могу понять, как.
Здесь мой класс 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 - это просто UserControl, который отображает данные (на данный момент только список строк).
Здесь, как я использую свой указатель строки
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");
}
Извините за дамп кода, но я не хотел пропустить что-то релевантное.
Ответы
Ответ 1
Итак, я получил его после чтения Pro WPF в С# 2008 (Страница 726).
В принципе, для класса DocumentViewer необходим файл XPS, чтобы представить его предварительный просмотр. Поэтому я делаю следующее:
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();
}
Я создаю диалог печати, чтобы получить размер страницы по умолчанию. Вероятно, это лучший способ сделать это.
XpsDocument находится в ReachFramework.dll(Namespace System.Windows.Xps.Packaging);
Здесь окно PrintPreview.
<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>
В коде только что имеется свойство Document:
public IDocumentPaginatorSource Document
{
get { return viewer.Document; }
set { viewer.Document = value; }
}
Ответ 2
В следующем коде MemoryStream используется предварительный просмотр печати.
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();
Не забудьте использовать функцию close() и удалить пакет из PackageStore, когда предварительный просмотр печати закрыт.
Ответ 3
WPF не имеет встроенной функции предварительного просмотра печати, если вы хотите сделать предварительный просмотр печати, вам придется ее самостоятельно создать. К счастью, это не должно быть так сложно.
У вас уже есть код разбивки на страницы, который создает ваши объекты DocumentPage
. Эти объекты содержат Visual
, которые вы можете продолжить и отобразить в своем интерфейсе.
Что вы в итоге сделаете, разбивает страницы на весь ваш документ, собирая все объекты DocumentPage
, а затем отображая их визуальные изображения внутри прокрутки StackPanel
или что-то подобное. Это те же объекты DocumentPage
, которые вы затем можете отправить на принтер.
Ответ 4
Код WinForm для предварительного просмотра печати:
PrintPreviewDialog PrintPreviewDialog = new PrintPreviewDialog();
PrintPreviewDialog.Document = PrintDocument;
PrintPreviewDialog.ShowDialog();
P.s.: Оригинальный плакат прокомментировал, что это неправильный ответ для приложения WPF.
Ответ 5
XpsDocument doc = new XpsDocument("filename.xps", FileAccess.Read);
docViewer.Document = doc.GetFixedDocumentSequence();
doc.Close();
Ответ 6
Я не думаю, что есть встроенный способ сделать это
Вот как я работал в NHaml
var documentViewHostDialog = new DocumentDialog();
documentViewHostDialog.LoadDocument(load);
documentViewHostDialog.ShowDialog();
Где "загрузка" - это либо FlowDocument, либо IDocumentPaginatorSource
и вот 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
Надеюсь, что это сработает для вашего дела.