7

リピーター内にユーザー コントロールを動的に構築するかなり複雑なページがあります。このリピーターは、初期化前の Init ページ イベント中にバインドする必要がありますViewState。そうしないと、動的に作成されたユーザー コントロールの状態が保持されません。

これにより興味深いキャッチ 22 が作成されます。これは、リピーターをバインドするオブジェクトを最初のページの読み込み時に作成し、ユーザーが終了または保存するまでメモリに保持する必要があるためです。

このオブジェクトを保存するために使用することはできませViewStateんが、初期化中に使用できるため、セッションに保存することを余儀なくされました。

動作をエミュレートするために、非ポストバック中にセッション値を明示的に null にする必要があるため、これにも問題がありますViewState

このシナリオでは、管理を状態にするためのより良い方法が必要です。何か案は?

編集:の使用に関するいくつかの良い提案LoadViewStateがありますが、それを行ったときに状態が復元されないという問題がまだあります。

ここは、ページ構成が多少

ページ --> ユーザー コントロール --> リピーター --> 動的に作成された N 個のユーザー コントロール。

完全にカプセル化され、それが存在するページから独立するように設計されているため、オーバーライドさLoadViewStateれたものを親に入れました。UserControlそこが問題なのか気になります。

4

7 に答える 7

4

ページの LoadViewState メソッドが間違いなく答えです。一般的な考え方は次のとおりです。

protected override void LoadViewState( object savedState ) {
  var savedStateArray = (object[])savedState;

  // Get repeaterData from view state before the normal view state restoration occurs.
  repeaterData = savedStateArray[ 0 ];

  // Bind your repeater control to repeaterData here.

  // Instruct ASP.NET to perform the normal restoration of view state.
  // This will restore state to your dynamically created controls.
  base.LoadViewState( savedStateArray[ 1 ] );
}

SaveViewState は、上記で使用している savedState 配列を作成する必要があります。

protected override object SaveViewState() {
  var stateToSave = new List<object> { repeaterData, base.SaveViewState() };
  return stateToSave.ToArray();
}

次のようなコードを使用して、Init または Load でリピーターをバインドすることも忘れないでください。

if( !IsPostBack ) {
  // Bind your repeater here.
}
于 2008-11-09T20:26:24.223 に答える
1

LoadViewState イベントで動的コントロールを常に再作成してきました。作成する必要があるコントロールの数をビューステートに保存し、LoadViewState イベント内の LoadControl メソッドを使用して、その数のコントロールを動的に作成できます。このイベントでは、ViewState にアクセスできますが、ページ上のコントロールにはまだ復元されていません。

于 2008-09-05T07:11:55.523 に答える
1

ViewState の動作をエミュレートするために、非ポストバック中にセッション値を明示的に null にする必要があるため、これにも問題があります。

値を明示的に無効にする必要があるのはなぜですか(メモリ管理などは別として)? Page.IsPostback をチェックし、Session 変数を使用して何かを行うかどうかのオプションではありませんか?

于 2008-09-05T03:22:46.167 に答える
0

ViewState の動作をエミュレートするために、非ポストバック中にセッション値を明示的に null にする必要があります。

セッションでバインドしているオブジェクトを保存できない理由については、まだわかりません。そのオブジェクトをセッションに保存できれば、次のように動作するはずです。

  1. 最初の読み込みで、OnPreInit 中に最上位のユーザー コントロールをオブジェクトにバインドします。オブジェクトをセッションに保存します。これらのコントロールの Viewstate は自動的に保存されます。最初に Page_Load でコントロールをバインドする必要がある場合は問題ありませんが、次の手順に従うと、bind を呼び出す 2 つのイベントが発生することになります。
  2. ポストバック時に、セッションに保存したオブジェクトに対して OnPreInit メソッドでトップ ユーザー コントロールを再バインドします。ビューステートをロードする前に、すべてのコントロールを再作成する必要があります。次に、ビューステートが復元されると、値はビューステートにあるものに設定されます。ここでの唯一の注意点は、ポストバックで再度バインドするときに、同じ数のコントロールが再度作成されることを 100% 確認する必要があることです。Repeater、Gridviews などを内部に動的コントロールで使用するための鍵は、viewstate が読み込まれる前に、すべてのポストバックで再バインドする必要があることです。OnPreInit は通常、これを行うのに最適な場所です。フレームワークには、最初の読み込み時にすべての作業を Page_Load で行う必要があるという技術的な制約はありません。

これはうまくいくはずです。ただし、何らかの理由でセッションを使用できない場合は、コントロールをバインドした後にバインド対象をデータベースに保存し、データベースから引き出して再バインドするなど、少し異なるアプローチを取る必要があります。ポストバックごとにもう一度。

あなたの状況についての明らかな詳細が欠けていますか?コードを投稿せずに状況の微妙な点を説明するのは非常に難しいことはわかっています。

編集: このソリューションでは、OnInit へのすべての参照を OnPreInit に変更しました。MS が ASP.NET 2.0 でこの新しいイベントを導入したことを忘れていました。ページ ライフサイクルのドキュメントによると、OnPreInit は動的コントロールを作成/再作成する場所です。

于 2008-09-06T21:50:53.387 に答える
0

1)おそらくそれを機能させる方法があります...適切なタイミングでコントロールをツリーに追加する必要があります。早すぎると、ViewState を取得できません。遅すぎて、ViewState を取得できません。

2) わからない場合は、ホール ページのビューステートをオフにして、状態の変更をクエリ文字列だけに頼ることができますか? 以前はポストバックだったリンクは、別の URL (またはポストバック リダイレクト) へのリンクになります。

これにより、ページの重量が大幅に軽減され、ViewState の問題を回避しやすくなります。

于 2008-09-05T14:32:59.750 に答える
0
protected override void LoadViewState(object savedState)
{
   // Put your code here before base is called
   base.LoadViewState(savedState);
}

そうですか?それとも、コントロールが処理される順序を意味していましたか? それに対する答えは準ランダムだと思います。

また、Page_Load の前にバインド先のオブジェクトをロードできないのはなぜですか? 必要に応じて、ページのライフサイクル中いつでもビジネス レイヤーを呼び出すことができます。

于 2008-09-05T16:59:07.947 に答える
0

動的コントロールを作成するとき...初期ロード時にのみ入力します。あとで、ページ読み込みイベントでポストバックのコントロールを再作成すると、ビューステートは値の再入力を問題なく処理しているようです。

于 2008-09-07T01:05:34.463 に答える