打印控制指南与WPF中的数据绑定

时间:2011-07-06 07:28:56

标签: .net wpf printing

我需要打印绑定到WPF中的数据的控件,我将有一个用户控件,它将具有绑定到数据的Grid等控件,并且我想打印用户控件。我还需要支持分页,页眉和页脚以及插入自定义徽标。

是否有任何文章/示例代码可以帮助我入门。

1 个答案:

答案 0 :(得分:3)

虽然向打印机发送视觉效果非常简单,但如果您需要处理分页,缩放,页眉和页脚,则可以更多地参与其中。但即使这并不是那么困难,您可以通过编写用户xaml用户控件来生成打印输出。我喜欢这个printing overview on MSDN来了解工作流程的一般情况。

要进行分页,您需要创建一个继承自System.Windows.Documents.DocumentPaginator的类。此类允许您告诉打印机要打印的页面以及每页上的项目排列方式。

在paginator中,您将通过实例化要打印的用户控件以编程方式构建页面。如果需要页眉/页脚,则为这些创建用户控件,实例化它们,设置任何所需的DataContext属性,并将它们添加到页面中。在大多数情况下,您可以以编程方式创建类似Grid的内容,配置列/行,向其添加用户控件,然后将其作为可视化返回。

一个技巧......你可能需要强制布局系统来布局控件。当您在屏幕上显示时会自动完成此操作,但如果您手动创建,则需要自己执行此操作:

        var pageSize = new Size(8.5 * 96.0, 11.0 * 96.0);
        var pageRect = new Rect(new Point(0, 0), pageSize);
        ...
        // create root visual (like a grid) and add user controls
        ...
        root.Measure(pageSize);
        root.Arrange(pageRect);
        root.InvalidateVisual();
        root.UpdateLayout();

DocumentPaginator上的文档很好地解释了如何使用该类。但是对于分页数据的情况,您可能需要自己做。我通常会确定页面的大小以及该页面上可以容纳的行数。然后我以编程方式将数据拆分成多个集合。也许每个系列中有25个项目。然后我将一组绑定到每个页面的列表/网格。

最后,你需要将它送到打印机。这大致是我用来创建XPS文档并将其发送到打印机的内容。并且...您可以使用此变体轻松显示打印预览对话框。只需创建一个对话框,其中包含一个显示XPS文档的FixedDocumentViewer。

public static string Print(DocumentPaginator paginator, string printQueueName, string documentName)
{
    using (MemoryStream xpsStream = new MemoryStream())
    {
        using (Package package = Package.Open(xpsStream, FileMode.Create, FileAccess.ReadWrite))
        {
            string packageUriString = "memorystream://data.xps";
            Uri packageUri = new Uri(packageUriString);

            try
            {
                PackageStore.AddPackage(packageUri, package);

                using (XpsDocument xpsDocument = new XpsDocument(package, CompressionOption.Maximum, packageUriString))
                {
                    PrintTicket printTicket = new PrintTicket();
                    printTicket.PageMediaSize = new PageMediaSize(paginator.PageSize.Width, paginator.PageSize.Height);

                    var writer = XpsDocument.CreateXpsDocumentWriter(xpsDocument);
                    writer.Write(paginator, printTicket);

                    FixedDocumentSequence document = xpsDocument.GetFixedDocumentSequence();

                    xpsDocument.Close();

                    PrintQueue targetQueue = null;

                    // Get the queue.
                    if (!string.IsNullOrEmpty(printQueueName))
                    {
                        var printServer = new LocalPrintServer();
                        targetQueue = printServer.GetPrintQueue(printQueueName);
                    }

                    // If no queue, then ask the user for a queue.
                    if (null == targetQueue)
                    {
                        var printDialog = new PrintDialog();
                        printDialog.PrintTicket = printTicket;
                        printDialog.UserPageRangeEnabled = false;
                        var response = printDialog.ShowDialog();

                        if (response.GetValueOrDefault() && null != printDialog.PrintQueue)
                        {
                            targetQueue = printDialog.PrintQueue;
                        }
                        else
                        {
                            return null;
                        }
                    }

                    var targetQueueWriter = PrintQueue.CreateXpsDocumentWriter(targetQueue);

                    document.Name = documentName;
                    targetQueueWriter.Write(document);
                    return document.Name;
                }
            }
            finally
            {
                PackageStore.RemovePackage(packageUri);
            }
        }
    }
}