Solución:
Lo que quieres hacer es crear un xpsDocument
del contenido que desea imprimir (un flowDocument
) y usa eso XpsDocument
para obtener una vista previa del contenido, por ejemplo, digamos que tiene lo siguiente Xaml, con un flowDocument
que desea imprimir su contenido:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<FlowDocumentScrollViewer>
<FlowDocument x:Name="FD">
<Paragraph>
<Image Source="http://www.wpf-tutorial.com/images/logo.png" Width="90" Height="90" Margin="0,0,30,0" />
<Run FontSize="120">WPF</Run>
</Paragraph>
<Paragraph>
WPF, which stands for
<Bold>Windows Presentation Foundation</Bold> ,
is Microsoft's latest approach to a GUI framework, used with the .NET framework.
Some advantages include:
</Paragraph>
<List>
<ListItem>
<Paragraph>
It's newer and thereby more in tune with current standards
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
Microsoft is using it for a lot of new applications, e.g. Visual Studio
</Paragraph>
</ListItem>
<ListItem>
<Paragraph>
It's more flexible, so you can do more things without having to write or buy new controls
</Paragraph>
</ListItem>
</List>
</FlowDocument>
</FlowDocumentScrollViewer>
<Button Content="Print" Grid.Row="1" Click="Button_Click"></Button>
</Grid>
el ejemplo de flowDocument es del sitio de tutoriales de Wpf
el botón de impresión Haga clic en el controlador de eventos debería tener este aspecto:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (File.Exists("printPreview.xps"))
{
File.Delete("printPreview.xps");
}
var xpsDocument = new XpsDocument("printPreview.xps", FileAccess.ReadWrite);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
writer.Write(((IDocumentPaginatorSource)FD).DocumentPaginator);
Document = xpsDocument.GetFixedDocumentSequence();
xpsDocument.Close();
var windows = new PrintWindow(Document);
windows.ShowDialog();
}
public FixedDocumentSequence Document { get; set; }
así que aquí estás principalmente:
- Crear un documento Xps y almacenarlo en un archivo printPreview.xps,
- Escribiendo el
FlowDocument
contenido en ese archivo, - pasando el
XpsDocument
alPrintWindow
en el que manejará la vista previa y las acciones de impresión,
aquí como el PrintWindow
parece :
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.5*"/>
</Grid.ColumnDefinitions>
<StackPanel>
<Button Content="Print" Click="Button_Click"></Button>
<!--Other print operations-->
</StackPanel>
<DocumentViewer Grid.Column="1" x:Name="PreviewD">
</DocumentViewer>
</Grid>
y el código detrás:
public partial class PrintWindow : Window
{
private FixedDocumentSequence _document;
public PrintWindow(FixedDocumentSequence document)
{
_document = document;
InitializeComponent();
PreviewD.Document =document;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//print directly from the Xps file
}
}
el resultado final se parece a esto
Ps: para usar XpsDocument, debe agregar una referencia al espacio de nombres System.Windows.Xps.Packaging
Sus requisitos se pueden lograr de varias formas, por ejemplo, puede utilizar el PrintDialog
clase. Las siguientes páginas de MSDN contienen descripciones, así como algunos códigos de muestra:
- WinForms: System.Windows.Forms.PrintDialog
- WPF: System.Windows.Controls.PrintDialog (gracias a Bartosz)
Alternativamente, se puede lograr a través de C #, por ejemplo, considere el siguiente código:
private string _previewWindowXaml =
@"<Window
xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"
xmlns:x ='http://schemas.microsoft.com/winfx/2006/xaml'
Title="Print Preview - @@TITLE"
Height="200" Width="300"
WindowStartupLocation ='CenterOwner'>
<DocumentViewer Name="dv1"/>
</Window>";
internal void DoPreview(string title)
{
string fileName = System.IO.Path.GetRandomFileName();
FlowDocumentScrollViewer visual = (FlowDocumentScrollViewer)(_parent.FindName("fdsv1"));
try
{
// write the XPS document
using (XpsDocument doc = new XpsDocument(fileName, FileAccess.ReadWrite))
{
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
writer.Write(visual);
}
// Read the XPS document into a dynamically generated
// preview Window
using (XpsDocument doc = new XpsDocument(fileName, FileAccess.Read))
{
FixedDocumentSequence fds = doc.GetFixedDocumentSequence();
string s = _previewWindowXaml;
s = s.Replace("@@TITLE", title.Replace("'", "'"));
using (var reader = new System.Xml.XmlTextReader(new StringReader(s)))
{
Window preview = System.Windows.Markup.XamlReader.Load(reader) as Window;
DocumentViewer dv1 = LogicalTreeHelper.FindLogicalNode(preview, "dv1") as DocumentViewer;
dv1.Document = fds as IDocumentPaginatorSource;
preview.ShowDialog();
}
}
}
finally
{
if (File.Exists(fileName))
{
try
{
File.Delete(fileName);
}
catch
{
}
}
}
}
Qué hace: en realidad imprime el contenido de un objeto visual en un documento XPS. Luego carga el documento XPS “impreso” y lo muestra en un archivo XAML muy simple que se almacena como una cadena, en lugar de como un módulo separado, y se carga dinámicamente en tiempo de ejecución. La ventana resultante tiene los botones de DocumentViewer: imprimir, ajustar al ancho máximo de página, etc.
También agregué un código para ocultar el cuadro de búsqueda. Ver esta respuesta a WPF: ¿Cómo puedo eliminar el cuadro de búsqueda en un DocumentViewer? por cómo hice eso.
El efecto es así:
El XpsDocument se puede encontrar en ReachFramework dll y el XpsDocumentWriter se puede encontrar en System.Printing dll, los cuales deben agregarse como referencias al proyecto.