WinUI3中如何实现无预览静默打印XAML页面(指定Microsoft Print to PDF打印机)
WinUI3中如何实现无预览静默打印XAML页面(指定Microsoft Print to PDF打印机)
嘿,刚好我之前研究过类似的需求,给你两种解决方案,看哪种更符合你的预期~
方案一:跳过打印预览,直接弹出PDF保存对话框(基于Windows.UI.Xaml.Printing框架)
这个方案是在你现有的Windows.UI.Xaml.Printing示例基础上修改的,点击按钮后会直接触发Microsoft Print to PDF的保存流程,跳过默认的打印预览窗口:
步骤1:初始化打印相关对象
在你的页面类中定义所需的变量,并在页面加载时完成初始化:
private PrintDocument _printDocument; private PrintManager _printManager; private FrameworkElement _printContent; // 要打印的XAML元素(比如当前Page或某个Grid) public MainPage() { this.InitializeComponent(); _printContent = this; // 这里假设打印当前整个页面,你可以替换成目标元素 InitializePrinting(); } private void InitializePrinting() { _printManager = PrintManager.GetForCurrentView(); _printManager.PrintTaskRequested += PrintManager_PrintTaskRequested; _printDocument = new PrintDocument(); _printDocument.Paginate += PrintDocument_Paginate; _printDocument.GetPreviewPage += PrintDocument_GetPreviewPage; _printDocument.AddPages += PrintDocument_AddPages; }
步骤2:实现打印内容的核心事件
这几个事件是告诉系统要打印什么内容,和普通打印预览的逻辑一致:
// 设置打印页数 private void PrintDocument_Paginate(object sender, PaginateEventArgs e) { _printDocument.SetPreviewPageCount(1, PreviewPageCountType.Final); } // 返回预览页(虽然跳过预览,但系统仍需要这个步骤生成打印内容) private void PrintDocument_GetPreviewPage(object sender, GetPreviewPageEventArgs e) { _printDocument.SetPreviewPage(e.PageNumber, _printContent); } // 添加要打印的页面 private void PrintDocument_AddPages(object sender, AddPagesEventArgs e) { _printDocument.AddPage(_printContent); _printDocument.AddPagesComplete(); }
步骤3:指定打印机并触发打印
在打印按钮的点击事件中触发打印流程,同时在PrintTaskRequested事件中指定目标打印机:
// 打印按钮点击事件 private async void PrintToPdfButton_Click(object sender, RoutedEventArgs e) { try { // 触发打印流程 await PrintManager.ShowPrintUIAsync(); } catch (Exception ex) { var errorDialog = new ContentDialog { Title = "打印失败", Content = $"出错啦:{ex.Message}", PrimaryButtonText = "确定" }; await errorDialog.ShowAsync(); } } // 打印任务请求事件,指定打印机 private void PrintManager_PrintTaskRequested(PrintManager sender, PrintTaskRequestedEventArgs args) { var deferral = args.Request.GetDeferral(); // 创建打印任务 var printTask = args.Request.CreatePrintTask("XAML页面转PDF", sourceArgs => { // 设置打印源 sourceArgs.SetSource(_printDocument.DocumentSource); // 指定目标打印机为Microsoft Print to PDF printTask.PrinterDisplayName = "Microsoft Print to PDF"; // 隐藏不必要的打印选项,让界面更简洁 printTask.Options.DisplayedOptions.Clear(); printTask.Options.DisplayedOptions.Add(PrintOptionName.Orientation); printTask.Options.DisplayedOptions.Add(PrintOptionName.MediaSize); }); // 监听打印完成状态 printTask.Completed += (s, e) => { if (e.Completion == PrintTaskCompletion.Failed) { _ = DispatcherQueue.TryEnqueue(async () => { var failDialog = new ContentDialog { Title = "打印失败", Content = "无法完成PDF生成", PrimaryButtonText = "确定" }; await failDialog.ShowAsync(); }); } }; deferral.Complete(); }
这个方案的效果是:点击按钮后直接弹出Microsoft Print to PDF的保存文件对话框,用户选择路径后即可生成PDF,完全跳过了打印预览环节。
方案二:完全静默打印,自动生成PDF(无需用户交互)
如果你需要完全不需要用户操作,自动将PDF保存到指定路径,可以用这个方案,不过需要用到System.Printing相关的API:
步骤1:添加必要的命名空间
using System.Printing; using System.IO; using Windows.UI.Xaml.Media.Imaging;
步骤2:实现静默打印方法
private async void SilentPrintButton_Click(object sender, RoutedEventArgs e) { try { // 1. 先把XAML页面转成临时XPS文件(打印队列需要XPS格式的源) var tempXpsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TempPrint.xps"); await SaveXamlElementToXps(_printContent, tempXpsPath); // 2. 获取Microsoft Print to PDF的打印队列 var localPrintServer = new LocalPrintServer(); var pdfPrintQueue = localPrintServer.GetPrintQueue("Microsoft Print to PDF"); // 3. 提交打印作业 var printJob = pdfPrintQueue.AddJob("静默生成PDF", tempXpsPath, false); // 4. 等待打印完成 while (!printJob.IsCompleted && !printJob.IsFailed && !printJob.IsCanceled) { await Task.Delay(100); } // 5. 清理临时文件 if (File.Exists(tempXpsPath)) { File.Delete(tempXpsPath); } // 提示成功 var successDialog = new ContentDialog { Title = "生成成功", Content = "PDF已自动保存到系统默认路径(通常是「文档」文件夹)", PrimaryButtonText = "确定" }; await successDialog.ShowAsync(); } catch (Exception ex) { var errorDialog = new ContentDialog { Title = "静默打印失败", Content = $"错误信息:{ex.Message}", PrimaryButtonText = "确定" }; await errorDialog.ShowAsync(); } } // 将XAML元素转换为XPS文件的辅助方法 private async Task SaveXamlElementToXps(FrameworkElement element, string outputPath) { var renderBitmap = new RenderTargetBitmap(); await renderBitmap.RenderAsync(element); using (var xpsDoc = new XpsDocument(outputPath, FileAccess.ReadWrite)) { var xpsWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc); xpsWriter.Write(renderBitmap); } }
注意事项
- 这个方案生成的PDF会保存在Microsoft Print to PDF的默认输出路径(一般是
C:\Users\你的用户名\Documents),如果要自定义保存路径,需要修改系统注册表或者使用第三方PDF打印机(不推荐修改注册表,可能影响系统稳定性)。 - 需要确保你的应用有足够的文件访问权限,比如在
Package.appxmanifest中添加「文档库访问」权限。
备注:内容来源于stack exchange,提问作者Biryukov Georgy
相关产品推荐
相关产品推荐

