web-dev-qa-db-ja.com

WPFからの印刷/レポートへの最適なアプローチは何ですか?

私は、そのデータから簡単なレポートを印刷できるようにしなければならない今後のプロジェクトを持っています。それはWPFベースであり、私はどちらに行くべきか疑問に思っています。

WPFには、非常に使いやすい独自の印刷技術(XPSベース)が導入されていることがわかります。ただし、ReportViewerコントロールを使用してWindows Forms Hostコントロールに埋め込む方が簡単かどうか疑問に思う人もいます。これにより、ユーザーはさまざまな形式にエクスポートして印刷できるようになります。

WPFからの印刷/レポートの経験はありますか?どの方向をお勧めしますか?

70
Matt Hamilton

これと同じ問題が発生し、今のところRDLC/ReportViewerを使用しています。ネイティブのWPFレポートツール(私が知っている)はなく、RDLCは非常に使いやすく、無料です。ランタイムのオーバーヘッドはわずか(約2Mb)ですが、.NET Frameworkの一部ではないため、配布することを忘れないでください。

25
Bob King

RDLの制限

私はもともとWPFでの印刷にRDLC/ReportViewerを使用しましたが、非常に制限されていることがわかりました。私が見つけた制限のいくつかは次のとおりです。

  • RDLは最も退屈なレポートしか作成できませんでした
  • RDLを使用してレポートを作成するのは、単純なWPFよりもはるかに手間がかかりました。設計ツールは、Expression Blendと比較して非常に原始的であり、テーブルでのみRDLを処理します
  • ControlTemplates、DataTemplates、Stylesなどを使用する機能がありませんでした
  • レポートのフィールドと列は、データサイズに基づいて効果的にサイズ変更および再配置できませんでした
  • グラフィックは画像​​としてインポートする必要がありました-ベクターとして描画または編集できませんでした
  • データバインディングではなくコードビハインドが必要なアイテムの配置
  • 変換の欠如
  • 非常に原始的なデータバインディング

WPFから直接印刷するのは非常に簡単です

これらの制限のため、純粋なWPFを使用してレポートを作成することを検討しましたが、それは非常に簡単なものであることがわかりました。 WPFでは、ページを生成できる独自のDocumentPaginatorサブクラスを実装できます。

Visualを取得し、ビジュアルツリーを分析し、選択した要素を非表示にして各ページを作成する単純なDocumentPaginatorサブクラスを開発しました。

DocumentPaginatorの詳細

以下は、初期化中にDocumentPaginatorサブクラスが行うことです(最初のPageCountがフェッチされたとき、または最初のGetPage()呼び出し中に呼び出されます)。

  1. ビジュアルツリーをスキャンし、ItemsControls内のすべてのスクロールパネルのマップを作成します
  2. 一番外側から始めて、スクロールする必要なしにVisualが単一のページに収まるまで、ItemsControlsの項目を最初から最後まで非表示にします。最外部を十分に縮小できない場合は、内部パネルが成功するか、各レベルでアイテムが1つだけになるまで内部パネルを縮小します。表示されるアイテムのセットを最初のページとして記録します。
  3. 最初のページに既に表示されている最下位レベルのアイテムを非表示にし、ページに収まらなくなるまで後続のアイテムを表示します。最後に追加したアイテムを除くすべてを2ページ目に記録します。
  4. すべてのページに対してプロセスを繰り返し、結果をデータ構造に保存します。

私のDocumentPaginatorのGetPageメソッドは次のとおりです。

  1. 初期化中に生成されたデータ構造で指定されたページ番号を検索します
  2. データ構造に示されているように、ビジュアルツリーの項目を非表示および表示します
  3. レポートがページ番号を表示できるように、PageNumberおよびNumberOfPages添付プロパティを設定します
  4. Dispatcher(Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));)をフラッシュして、バックグラウンドレンダリングタスクを完了させます
  5. VisualBrushが印刷されるビジュアルであるページのサイズの四角形を作成します
  6. 長方形を測定、配置、および更新レイアウトし、それを返します

これは非常に単純なコードであることが判明し、WPFで作成できるものなら何でもページに変換して印刷することができました。

追加のレポートサポート

これでページネータが機能するようになったので、スクリーン用または紙用のWPFコンテンツを作成するかどうかについてあまり心配する必要がなくなりました。実際、データ入力と編集用に作成したUIは、印刷にも非常によく機能します。

そこから単純なツールバーといくつかのコードビハインドを追加し、RDLよりもはるかに優れたWPFを中心に構築された本格的なレポートシステムを作成しました。レポートコードは、ファイルへのエクスポート、プリンターへの印刷、ページイメージの切り取り/貼り付け、およびExcelのデータの切り取り/貼り付けを行うことができます。チェックボックスをクリックするだけで、UIを「印刷ビュー」に切り替えて、印刷した場合の外観を確認することもできます。これらはすべて、わずか数百行のC#およびXAMLで実現できます。

この時点で、レポートコードにないRDLの機能は、書式設定されたExcelスプレッドシートを生成する機能だけだと思います。これをどのように行うことができるかはわかりますが、これまでのところ必要はありませんでした。データの切り取りと貼り付けだけで十分でした。

私の経験からは、ページネータを作成し、WPF自体を使用してレポートを作成することをお勧めします。

42
Ray Burns

http://wpfreports.codeplex.com/ を見てください

8
Lukas Cenovsky

Scryberはどうですか? PDFレポートテンプレートをxmlを使用して定義し、実行時にアプリケーション内のデータにバインドすることができます。 http://scryber.codeplex.com/

3
LiamV

PdfReports をご覧ください。これは、iTextSharpおよびEPPlusライブラリの上に構築されたコードファーストのレポートエンジンです。 .NET 3.5+ WebおよびWindowsアプリケーションの両方と互換性があります。

3
VahidN

Ray Burnsの回答を詳しく説明するには、実装例を探している場合は、以下を参照してください。 Custom Data Grid Document Paginator

これは素晴らしい出発点です。

2

私は、基本的に設計環境とデータソースマネージャーで構成される独自のレポートシステムを開発するタスクを最近達成しました。最初のタスクは、WYSWIGに似た設計環境を開発することでした。 GDI +を使用してこれを行いましたが、印刷を気にしなくても、印刷/印刷プレビューの生成は思ったよりも簡単でした。一般に、画面上のすべてのものを印刷イベントのグラフィックオブジェクトに描画するだけです。

WPFの場合も同様であると思うので、画面上にレポートを表示するだけで、印刷はほんの数行のコードになるだけです。

1
MoreThanChaos

WPFの将来に関する全体的な政治的議論に入ることなく、私たちが見つけた最良の選択肢は、ReportViewerをWindows Forms Hostコントロールにラップすることでした。

http://blog.pineywoodstech.com/index.php/2012/01/using-Microsoft-reportviewer-with-wpf/

0
Doug