Какой лучший подход к печати/отчетности из WPF?

У меня есть предстоящий проект, который должен будет иметь возможность печатать простые отчеты из своих данных. Это будет WPF-based, и мне интересно, куда идти.

Я знаю, что WPF представляет свою собственную технологию печати (на основе XPS), которая выглядит довольно проста в использовании. Тем не менее, часть меня задается вопросом, будет ли проще использовать элемент управления ReportViewer и встроить его в элемент управления хостом Windows Forms, поскольку это даст пользователям возможность экспортировать в различные форматы, а также распечатать.

Есть ли у кого-нибудь опыт печати/отчетности из WPF? Какое направление вы бы порекомендовали?

Ответ 1

У нас была эта же проблема, и в итоге я использовал RDLC/ReportViewer. Там нет встроенного средства отчетности WPF (что я знаю) и RDLC довольно прост в использовании и является бесплатным. Накладные расходы во время выполнения невелики (около 2 МБ), но вы должны помнить о том, чтобы распространять его, поскольку он не является частью .NET Framework.

Ответ 2

Ограничения RDL

Я изначально отправился с RDLC/ReportViewer для печати с помощью WPF, но нашел его очень ограниченным. Некоторые из ограничений, которые я нашел, были:

  • RDL может создавать только самые скучные отчеты
  • Было гораздо больше работы по созданию отчета с использованием RDL, чем в прямом WPF: инструменты проектирования очень примитивны по сравнению с Expression Blend и RDL сделок только в таблицах
  • У меня не было возможности использовать ControlTemplates, DataTemplates, Styles и т.д.
  • Мои поля и столбцы отчета не могут эффективно изменять размер и изменять размер данных на основе размера данных
  • Графика должна была быть импортирована как изображения - ее нельзя было нарисовать или отредактировать как векторы
  • Позиционирование элементов, требующих замены кода, а не привязки данных
  • Отсутствие преобразований
  • Очень примитивная привязка данных

Печать непосредственно из WPF очень проста

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

Я разработал простой подкласс DocumentPaginator, который принимает любой Visual, анализирует визуальное дерево и скрывает выбранные элементы для создания каждой страницы.

Сведения о DocumentPaginator

Вот что делает мой подкласс DocumentPaginator во время инициализации (вызывается при первом выборе PageCount или во время первого вызова GetPage()):

  • Сканирование визуального дерева и создание карты всех прокрученных панелей внутри ItemsControls
  • Начиная с самого внешнего, элементы в элементах ItemsControls невидимы для первого, пока Visual не подходит для одной страницы без необходимости прокрутки. Если внешний уровень не может быть уменьшен достаточно, уменьшает количество внутренних панелей до тех пор, пока это не удастся или не будет иметь только один элемент на каждом уровне. Запишите набор видимых элементов в качестве первой страницы.
  • Скрыть элементы самого низкого уровня, которые уже были показаны на первой странице, затем сделать последующие элементы видимыми, пока они больше не будут помещаться на странице. Запишите все, кроме последнего, как вторую страницу.
  • Повторите процесс для всех страниц, сохранив результаты в структуре данных.

Мой метод GetPage My DocumentPaginator выглядит следующим образом:

  • Посмотрите номер данной страницы в структуре данных, сгенерированной во время инициализации.
  • Скрыть и отобразить элементы в визуальном дереве, как указано в структуре данных
  • Установить атрибуты PageNumber и NumberOfPages, чтобы в отчете отображалась нумерация страниц
  • Выполните сброс Диспетчера (Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));), чтобы завершить выполнение задач фонового рендеринга
  • Создайте прямоугольник размером страницы, чья визуальная визуализация будет напечатана
  • Измерить, упорядочить и обновитьLayout прямоугольник, а затем вернуть его

Это оказался довольно простой код и позволил мне превратить практически все, что я мог создать с помощью WPF на страницы и распечатать его.

Дополнительная поддержка отчетов

Теперь, когда мой paginator работает, мне больше не нужно очень беспокоиться о том, создаю ли я свой контент WPF для экрана или бумаги. На самом деле, часто пользовательский интерфейс, который я создаю для ввода и редактирования данных, также очень хорошо работает для печати. ​​

Оттуда я добавил простую панель инструментов и некоторый код, что привело к созданию полноценной системы отчетов, построенной вокруг WPF, которая была гораздо более способной, чем RDL. Мой код отчетности может экспортироваться в файлы, печатать на принтер, вырезать/вставлять изображения страниц и вырезать/вставлять данные для Excel. Я также могу переключить любой из моих пользовательских интерфейсов, чтобы "распечатать вид", щелкнув флажок, чтобы увидеть, как он будет выглядеть, если будет напечатан. Все это всего за несколько сотен строк С# и XAML!

На данный момент я считаю, что единственная функция, которую RDL имеет, что мой код отчетности не имеет, - это возможность создавать форматированную электронную таблицу Excel. Я вижу, как это можно было бы сделать, но до сих пор не было необходимости - разрезание и вставка только данных были достаточно.

По моему опыту моя рекомендация заключалась бы в написании страницы, а затем начать использовать WPF для создания ваших отчетов.

Ответ 4

Посмотрите PdfReports. Это первый механизм создания кода, который построен поверх библиотек iTextSharp и EPPlus. Он совместим с приложениями .NET 3.5+ Web и Windows.

Ответ 7

Как насчет Scryber? Он позволяет определять шаблоны отчетов PDF с помощью xml и привязываться к данным в вашем приложении во время выполнения. http://scryber.codeplex.com/

Ответ 8

Я успешно выполнил задачу разработки собственной системы отчетности, которая в основном состоит из среды проектирования и источника данных. Первая задача заключалась в разработке WYSWIG-подобной конструкции. Я сделал это с помощью GDI +, даже не заботясь о печати, так как вышло, что печать/генерация предварительного просмотра печати была проще всего, чем я ожидал. В общем, требуется всего лишь нарисовать все на экране графический объект события печати.

Я думаю, что в случае WPF это было бы похоже, так что все, о чем вы должны беспокоиться, это отобразить отчет на экране, а печать будет всего лишь несколькими строками кода.