- PR -

[ASP.NET]WebFormの状態を再現したい

投稿者投稿内容
junya_s0
常連さん
会議室デビュー日: 2002/12/23
投稿数: 26
投稿日時: 2003-12-02 15:11
こんにちは。
現在、VB.NETでASP.NETアプリケーションを開発しています。

2画面構成で1画面目が条件入力画面、2画面目が検索結果表示画面となっており、2画面目には「戻る」ボタンがあって、押すと1画面目に戻ります。

ここで「戻る」ボタンを押したときに、「2画面目を表示する前に入力した条件がセットされている1画面目」を表示したいのです。

1画面目のViewStateをセッション変数に保存しておき、1画面目の再ロード時にそれを読み込もうとしたのですが方法が分かりませんでした。
また、条件入力画面にはグリッドのコントロールを使用しており、1つ1つの値を保持しておいてそれをセットするというのはできればやりたくない方法です。

何か良いアドバイスがあれば、よろしくお願いします。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-12-02 17:49
 同じようなことをしようと試みていますが、私は単純にシリアライザでシリアル化するつもりでした。

 ViewStateでやるなら、SaveViewStateメソッドで、ViewStateをセッション変数に放り込み、PageLoadイベントで何らかの判定でセッション変数から取り出し、LoadViewStateメソッドを呼び出してやればいいのではないでしょうか。

 思いつきで書いているので、それなりに調べてください。結果をフィードバックしていただけるとうれしいです。
junya_s0
常連さん
会議室デビュー日: 2002/12/23
投稿数: 26
投稿日時: 2003-12-02 19:56
Jittaさん、回答ありがとうございます。

とりあえず、1ページ目のButton_ClickでPage.SaveViewStateメソッドを呼んでみたのですが、Nothingが返ってきてしまいました。
Page_LoadやPage_Initなど他の箇所で呼んでみても値は返ってこず、ヘルプによるとViewStateが無い場合はNothingが返るとのことなので、ページではなく各コントロールのSaveViewStateを呼んでみようとしたのですが、Protectedで定義されておりアクセスできませんでした。

ViewStateを使用するのは無理なのですかね・・・。
誰かご存知の方いらっしゃいませんか?

[ メッセージ編集済み 編集者: junya_s0 編集日時 2003-12-02 20:29 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-12-03 13:14
引用:

junya_s0さんの書き込み (2003-12-02 19:56) より:

とりあえず、1ページ目のButton_ClickでPage.SaveViewStateメソッドを呼んでみたのですが、Nothingが返ってきてしまいました。


 よく読んでください。
引用:

SaveViewStateメソッドで、ViewStateをセッション変数に放り込み


と書きましたすよね。SaveViewStateメソッドがコールされるのはイベントハンドラを処理した後です。また、ViewStateに入れるべき値が設定されるのはレンダリングの状態が整ったときです。イベントの発生順序については「.NET Framework 開発者ガイド コントロール実行の有効期間」を見てください。

 かいつまんで説明すると、クライアントからのリクエストを受けると、
コントロールの初期化→ユーザによる初期設定→ポストバックによるイベントの処理→表示準備→表示処理の一環としての保存(SaveViewState)→表示処理
の順です。つまり、ViewStateに設定すべき値は「表示準備」が整ったときに設定されるのであり、イベントハンドラでSaveViewStateを呼んでも、値の準備が整っていないので(全てのイベントが終了しないと、値が変更される可能性があるでしょ?)、何も返ってこないわけです。

 そういうわけなので、SaveViewStateをオーバライドし、親クラスのSaveViewStateをコールした後、セッション変数にしまってください。



 それから、未確認ですが、カスタムコントロールを作るときにInitializeイベントハンドラを記述する、またはInitializeメソッドをオーバーライドすると、ViewStateに設定するべき値が設定されないようです。
junya_s0
常連さん
会議室デビュー日: 2002/12/23
投稿数: 26
投稿日時: 2003-12-03 13:59
引用:

SaveViewStateメソッドで、ViewStateをセッション変数に放り込み


上記は「SaveViewStateメソッドを使って〜」という意味だと思ってました。
イベントの発生順について勉強不足で理解しきれてませんでした。

で、PageのSaveViewStateをこんな感じにオーバーライドしてみました。
コード:
    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If Not (IsPostBack) Then
            If Not (Session("VS") Is Nothing) Then
                LoadViewState(Session("VS"))
            End If
        End If
    End Sub

    Protected Overrides Function SaveViewState() As Object
        Dim obj As Object
        obj = MyBase.SaveViewState()

        '===いずれかを有効に
        'Session("VS") = obj              '(1)
        'Session("VS") = Me.ViewState     '(2)
        'Session("VS") = MyBase.ViewState '(3)

        Return obj
    End Function



上記コードを実行した場合、(1)のパターンだと、objにNothingが入ってきます。
(2)(3)のパターンだとPage_LoadのLoadViewStateメソッドでInvalidCastExceptionが発生します。
メソッド呼び出し時点のSession("VS")のデータ型はSystem.Web.UI.StateBagでした。

上記コードで問題点はあるでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-12-03 15:37
 大変失礼しました。カスタムコンポーネントでViewStateをいじっていたため、勘違いをしていました。つまり、Page.ViewStateはページのViewStateであって、Pageに所属するコントロールのViewStateの塊、ではないということです。
#ちなみに、Pageには保持する要件がないので、Page.ViewStateは空のStateBagです

 それで、コントロールのイベントの発生順は、コントロールの階層構造順になるので、ページのイベントハンドラ/メソッドが実行され、コントロールのイベントハンドラ/メソッドが実行されます。つまり、ページのメソッドで、コントロールの同じメソッドで処理されるはずの値はアクセスできないと言うことです。PageのSaveViewStateでは、コントロールのVewStateはまだ設定されていない、ということです。
#う〜ん、図を書いて整理しておきながら、我ながら、情けない。


 ということは、『1つ1つの値を保持しておいてそれをセットするというのはできればやりたくない方法』をしなければならない、ということです。
 例えば、ViewStateを利用するにしても、Renderメソッドをオーバーライドして、親クラスのRenderメソッドをコールしてから、Forループで所有するコントロールを(再帰的に)回してViewStateを配列か何かに放り込むと言うことです。
junya_s0
常連さん
会議室デビュー日: 2002/12/23
投稿数: 26
投稿日時: 2003-12-03 16:12
なるほど・・・。
PageのSaveViewStateの時点では各コントロールのSaveViewStateが実行されていないためPageのViewStateには何も入っていないということですね。
了解しました。

ちなみに、PageのRenderをオーバーライドしてやってみましたが、各コントロールのViewStateがProtectedで定義されているのでアクセスできませんでした。

シリアル化する方向で考えてみることにします。

Jittaさん、大変お手数をおかけしてすいませんでした。
ありがとうございました。
POKKURI
会議室デビュー日: 2003/10/27
投稿数: 4
お住まい・勤務地: 大阪
投稿日時: 2005-04-25 18:53
古い内容をひっぱりだして申し訳ありません。
同様の問題で悩んでおりまして、このスレにたどりついたのですが、
結局どのようにして解決されたのかわからなかったので、再度質問させていただきます。

【要件】画面遷移時に前の画面の状態を保存しておいて後に復元する。

@入力画面A、入力画面B画面がある。
A入力画面Aの入力途中で入力画面Bに遷移してBの画面の入力を行う。
B入力画面Bの入力後入力画面Aに戻り、Aの入力を再開する。(画面Aは途中まで入力された内容が復元されている。)

Panelコントロールを使用する方法も検討していますが、できれば画面ごとにモジュールを分割したいので画面Aから画面BにHiddenまたはSessionを利用して画面の状態(ViewState)を引き継ぎたいのですが、良い方法が見つかりません。

よい方法をご存知の方がいらっしゃいましたらご教授よろしくお願いいたします。

スキルアップ/キャリアアップ(JOB@IT)