Руководство по управлению печатью, привязанным к данным в WPF - PullRequest
1 голос
/ 06 июля 2011

У меня есть требование для печати элементов управления, привязанных к данным в WPF, у меня будет пользовательский элемент управления, который будет иметь такие элементы управления, как Grid, привязанный к данным, и я хочу напечатать пользовательский элемент управления. Мне также нужна поддержка разбиения на страницы, верхний и нижний колонтитулы и вставка пользовательских логотипов.

Есть ли статья / пример кода, который поможет мне начать работу.

1 Ответ

3 голосов
/ 06 июля 2011

Несмотря на то, что отправлять изображение на принтер очень просто, он может быть немного сложнее, если вам нужно обрабатывать подкачку, масштабирование, верхние и нижние колонтитулы. Но даже это не так сложно, и вы можете сгенерировать печатный вывод, создав пользовательские элементы управления xaml. Мне нравится этот обзор печати на 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 и отправки его на принтер. И ... Вы можете использовать вариант этого, чтобы легко показать диалоговое окно предварительного просмотра печати. Просто создайте диалог, который содержит FixedDocumentViewer, который отображает документ XPS.

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);
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...