RDL の制限
私はもともと、WPF で印刷するために RDLC/ReportViewer を使用していましたが、非常に制限があることがわかりました。私が見つけた制限のいくつかは次のとおりです。
- RDL は最も退屈なレポートしか作成できませんでした
- RDL を使用してレポートを作成するのは、そのままの WPF よりもはるかに手間がかかりました。デザイン ツールは、Expression Blend と比較して非常に原始的であり、RDL はテーブルのみを扱います。
- ControlTemplates、DataTemplates、Styles などを使用する機能がありませんでした
- レポートのフィールドと列は、データ サイズに基づいて効果的にサイズ変更および再配置できませんでした
- グラフィックは画像としてインポートする必要があり、ベクターとして描画または編集することはできませんでした
- データ バインディングではなくコード ビハインドが必要なアイテムの配置
- 変換の欠如
- 非常に原始的なデータバインディング
WPFから直接印刷するのはとても簡単です
これらの制限があるため、純粋な WPF を使用してレポートを作成することを調べたところ、それは本当に簡単なことであることがわかりました。WPF では、DocumentPaginator
ページを生成できる独自のサブクラスを実装できます。
任意の Visual を取得し、ビジュアル ツリーを分析し、選択した要素を非表示にして各ページを作成する単純な DocumentPaginator サブクラスを開発しました。
DocumentPaginator の詳細
初期化中に DocumentPaginator サブクラスが行うことは次のとおりです (最初の PageCount がフェッチされるとき、または最初の GetPage() 呼び出し中に呼び出されます)。
- ビジュアル ツリーをスキャンし、ItemsControls 内のすべてのスクロール パネルのマップを作成します。
- 一番外側から順に、スクロールしなくても Visual が 1 ページに収まるまで、ItemsControls 内の項目を非表示にします。最も外側のパネルを十分に削減できない場合は、成功するか各レベルでアイテムが 1 つになるまで内側のパネルを削減します。目に見えるアイテムのセットを最初のページとして記録します。
- 最初のページに既に表示されている最下位レベルのアイテムを非表示にし、ページに収まらなくなるまで後続のアイテムを表示します。最後に追加された項目を除くすべてを 2 ページ目として記録します。
- すべてのページに対してプロセスを繰り返し、結果をデータ構造に保存します。
私の DocumentPaginator の GetPage メソッドは次のとおりです。
- 初期化中に生成されたデータ構造で指定されたページ番号を検索します
- データ構造に示されているように、ビジュアル ツリー内の項目を表示および非表示にする
- PageNumber および NumberOfPages 添付プロパティを設定して、レポートにページ番号を表示できるようにします
- Dispatcher (
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));
) をフラッシュして、バックグラウンド レンダリング タスクを完了させます。
- VisualBrush が印刷されるビジュアルであるページのサイズの Rectangle を作成します。
- 四角形を測定、配置、および UpdateLayout し、それを返します
これは非常に単純なコードであることが判明し、WPF で作成できるほとんどすべてのページをページに変換して印刷することができました。
追加のレポート サポート
ページネーターが機能するようになったので、WPF コンテンツを画面用に作成するのか紙用に作成するのかについてあまり心配する必要がなくなりました。実際、私がデータ入力と編集用に作成した UI は、印刷用にも非常にうまく機能することがよくあります。
そこから、単純なツールバーといくつかのコード ビハインドを追加した結果、RDL よりもはるかに優れた WPF を中心に構築された本格的なレポート システムが完成しました。レポート コードは、ファイルへのエクスポート、プリンターへの印刷、ページ イメージの切り取りと貼り付け、および Excel のデータの切り取りと貼り付けを行うことができます。チェックボックスをクリックして UI を「印刷ビュー」に切り替えて、印刷した場合の外観を確認することもできます。これらすべてが、わずか数百行の C# と XAML で実現されます。
この時点で、私のレポート コードにはない RDL の唯一の機能は、書式設定された Excel スプレッドシートを生成する機能だと思います。これがどのように行われるかはわかりますが、これまでのところその必要はありません。データをカット アンド ペーストするだけで十分です。
私の経験から、ページネーターを作成してから、WPF 自体を使用してレポートを作成することをお勧めします。