在WPF中利用XPS文档实现打印功能
摘要
WPF重新规划了打印模型,将所有编码围绕System.Windows.Controls.PrintDialog
,使用PrintDialog
类可显示Print对话框、设置打印机首选项等等,并且可将元素、文档以及低级的可视化元素直接发送给打印机。在WPF中实现打印的方式也有好几种,本文将使用XPS的方式简单实现一下打印功能。
代码实现
1、准备FlowDocument
模板以及模板中要显示的数据,之前已经分享过一篇该文章,传送门==>在WPF中将XAML文档转换为PDF文件导出 有需要跳转过去看一下,这里不再重复阐述
2、将数据填充至FlowDocument
private FlowDocument FillFlowDocument()
{
var doc = (FlowDocument)Application.LoadComponent(new Uri("/WPF_XPSDocumentPrint_Demo;component/Resources/StudentTemplate.xaml", UriKind.RelativeOrAbsolute));
doc.DataContext = new Models.Student
{
Name = "傲慢与偏见",
Class = "三年一班",
Chinese = 99,
Math = 59,
English = 66,
Comments = "此乃难得一见的奇才,未来可期!!!(Tips:这文字是绑定的,不是静态数据)"
};
return doc;
}
3、使用Package
开辟一个容器将模板写入
private FixedDocumentSequence _StudentDocument;
/// <summary>
/// 模板文档(绑定至前端要显示的文档视图中)
/// </summary>
public FixedDocumentSequence StudentDocument
{
get { return _StudentDocument; }
set { _StudentDocument = value; RaisePropertyChanged(); }
}
private delegate void LoadXpsMethod();
private MemoryStream ms;
private Package package;
private Uri DocumentUri;
public MainWindowViewModel()
{
var doc = FillFlowDocument();
Application.Current.Dispatcher.BeginInvoke(
new LoadXpsMethod(() => FillDocumentViewer(doc)), DispatcherPriority.ApplicationIdle);
}
private void FillDocumentViewer(FlowDocument doc)
{
try
{
ms = new MemoryStream();
package = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);
DocumentUri = new Uri("pack://InMemoryDocument.xps");
PackageStore.AddPackage(DocumentUri, package);
XpsDocument xpsDocument = new XpsDocument(package, CompressionOption.Fast, DocumentUri.AbsoluteUri);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
writer.Write(((IDocumentPaginatorSource)doc).DocumentPaginator);
StudentDocument = xpsDocument.GetFixedDocumentSequence();
xpsDocument.Close();
}
catch (Exception e)
{
MessageBox.Show("读取打印模板错误:{0}", e.ToString());
}
}
简单说下思路,就是先加载文档模板,并通过设置上下文给模板绑定数据,开辟一个内存流,使用Package
创建这个模板包,再写入到XPS文档中,最后通过XPS获取到一个FixedDocumentSequence
文档序列绑定到前台。
4、最后记得做一下必要的释放
public void Dispose()
{
PackageStore.RemovePackage(DocumentUri);
if (package != null)
{
package.Close();
package = null;
}
if (ms != null)
{
ms.Close();
ms = null;
}
DocumentUri = null;
}
效果
-
打印预览
-
调起PrintDialog
-
动效演示