次の方法で共有


Page_Load イベント ハンドラでレポートをバインドする際の永続の制限

ASP.NET の Web アプリケーションでは、一般的な方法として、ページを起動するすべてのコードを Page_Load イベント ハンドラに設定しています。Page_Load イベント ハンドラは、Page.Load イベントによって呼び出されます。

特に、コントロールをデータ バインドするコードは、通常、Page_Load イベント ハンドラに記述されます。ただし、このイベント ハンドラにバインド コードを記述すると、ViewState に問題が発生します。この問題と一般的な解決策は次のとおりです。

  • ViewState は、コントロールにバインドされたデータとコントロールで実行されるマウス クリック イベントの 2 つをページのリロードの間も維持するために使用されます。
  • ViewState は文字列です。そのため、データとクリック イベントをシリアライズする必要があります。
  • ページをリロードする際に、データとクリック イベントの両方が ViewState から復元されます。
  • Page.Load イベントは、ViewState が復元された後に発生します。コントロールをバインドするコードが Page_Load イベント ハンドラに記述されていると、ページのリロードで、このバインド コードが ViewState を上書きして、元のデータとクリック イベントが失われます。
  • この問題のよくある例として、ページのリロードによってコントロールがマウス クリック操作の情報を失う(DropDownList の選択など)場合があります。
  • データとマウス クリック イベントを上書きしないようにするには、Page_Load イベント ハンドラ内のバインド コードをすべて Not IsPostBack 条件ブロックに記述します。これで、バインド コードがポストバックで呼び出されなくなります。

この解決法は、データとマウス クリック イベントをどちらも ViewState にシリアライズできるという重要な仮定を行っています。ただし、CrystalReportViewer コントロールは、シリアライズできないオブジェクト(具体的には ReportDocument クラス、ReportClientDocument クラス、InfoObject クラス)にバインドします。

Note

唯一の例外は、CrystalReportViewer コントロールがファイル ディレクトリ パスによってレポートにバインドされる場合、パス文字列が ViewState に永続するということです。このシナリオに限り、CrystalReportViewer コントロールは Not IsPostBack 条件ブロックに配置できます。ただし、このレポート バインド シナリオは上にリストされたレポート クラスにバインドするほど強力ではなく、あまり一般的には使用されません。

CrystalReportViewer コントロールのマウス クリック イベントだけを ViewState にシリアライズできるため、シリアライズできないレポート クラスにバインドすると、ページのリロードで解決できない問題が発生します。

  • レポートをバインドするコードを Not IsPostBack 条件ブロックに記述すると、ViewState のマウス クリック イベントは保存されます。ただし、レポートのバインドは行われません。そのため、例外がスローされます。
  • レポートをバインドするコードが条件ブロックの外に記述されると、レポートは正しくバインドされます。ただし、処理中に ViewState が上書きされます。そのため、マウス クリック イベントは失われます。
    Note

    この状況は、CrystalReportViewer コントロールで複数のページを含むレポートをクリックする場合によく見られます。レポートはなぜか 1 ページ目を返し続けます。

推奨シナリオ:CrystalReportViewer コントロールのバインド コードを Init イベントに移動する

CrystalReportViewer コントロールの完全なソリューションは、ViewState の復元前に発生する Init イベントに、レポートをバインドするコードを移動することです。

このソリューションには、1 つ面倒な点があります。通常、Init イベントは、Load イベントほど頻繁には記述されないため、使用しにくくなっています。Visual Studio .NET 2003 での Web または Windows プロジェクトでは、Init イベントが扱うコードは[Web フォーム デザイナで生成されたコード]領域に配置されています。この領域は一般的に非表示で、生成されたコード用に予約されています。

これを解決するには、次の方法をお勧めします。

  • CrystalReportViewer のすべてのバインド コードおよび設定コードを ConfigureCrystalReports() という名前のプライベート ヘルパー メソッドに展開します。
  • [Web フォーム デザイナで生成されたコード]領域に、Page_Init() イベント ハンドラまたは OnInit() イベント起動メソッドの ConfigureCrystalReports() ヘルパー メソッドを呼び出す 1 行だけを配置します。

ConfigureCrystalReports() ヘルパー メソッドの作成と設定の手順は、「プロジェクトの設定」で説明されています。

チュートリアル

レポートの永続を完全に理解するために、次のチュートリアルで学習できます。

ReportDocument オブジェクト モデルでコード化する場合は、次のチュートリアルを使用します。