- PR -

動的に生成したTextBoxの値に関して

1
投稿者投稿内容
kei69
会議室デビュー日: 2004/12/18
投稿数: 2
投稿日時: 2004-12-18 11:10
こんにちは。Keiと申します。

現在 VisualStudio2003/vb.net
でWebアプリを開発しております。

現在とても困っていることがありまして、どなたかお力を貸して頂けませんでしょうか?

1. 動的にテキストボックスを作成する。(Page_Loadイベント時)
2. PostBackした時に同様にテキストボックスを作成し、値のみ書き換える。

上記を行いたいのですが、デバッグ時には正しく動作(書き換えた値がテキストボックスへ挿入される)するのですが、画面には反映されません。。。
この問題は.netの仕様だそうですが、どなたか回避方法をご存知ないでしょうか?
どうかよろしくお願いします。。。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-12-18 12:08
デバッグ時には正しく動作しているなら、リリース時とデバッグ時の違いに問題があるのであって、.NET Frameworkの仕様は関係ないのでは?
_________________
kei69
会議室デビュー日: 2004/12/18
投稿数: 2
投稿日時: 2004-12-18 12:20
Jitta様 ご返信ありがとうございます。

私の説明が足りなくて申し訳ありません。。。

現在下記問題を回避したいのです。

http://support.microsoft.com/default.aspx?scid=kb;ja;316813

Page_Load時にテキストボックスの値を書き換えているのですが、画面が生成された時点で、
PostBack前の値にまた書き換えられているようなのです。

回避方法ご存知ないでしょうか?
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2004-12-18 14:59
引用:
kei69さんの書き込み (2004-12-18 11:10) より:
1. 動的にテキストボックスを作成する。(Page_Loadイベント時)
2. PostBackした時に同様にテキストボックスを作成し、値のみ書き換える。

ほんとですね・・・確かにIsPostBackで設定した値がブラウザでは表示されませんね。
いままで気づきませんでした・・

2で新しくTextBoxを作成したときに
TextBox.ID = "適当なID"; //つまり1で作成したときと異なるIDにする
と、してみてはどうでしょうか?(IDを変えることが仕様的に可能なら)

引用:
デバッグ時には正しく動作(書き換えた値がテキストボックスへ挿入される)するのですが

これは、ブレークでとめたとき等の話ですよね?
デバックビルドでもブラウザには表示されないのですよね?
にしざき
ぬし
会議室デビュー日: 2003/06/30
投稿数: 304
投稿日時: 2004-12-18 14:59
もう少し具体的に問題を示していただけるとありがたいんですが。
差し支えない範囲のソースとか。
えんぞ@?
ぬし
会議室デビュー日: 2004/07/06
投稿数: 271
お住まい・勤務地: はまっこ
投稿日時: 2004-12-18 16:46
Page_PreRenderにて値をセットすれば、とりあえず一つの回避策となるかもしれません。

スレ主に代わって再現コードです。
-------------------------------
EnableViewState="False"
-------------------------------
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim TextBox1 As TextBox = New TextBox()
With TextBox1
.ID = "TextBox1"
If Not Me.IsPostBack Then
.Text = "First"
Else
.Text = "PostBack"
End If
Me.Panel1.Controls.Add(TextBox1)
End With
End Sub

'Private Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PreRender
' If Me.IsPostBack Then
' CType(Me.Panel1.FindControl("TextBox1"), TextBox).Text = "PostBack2"
' End If
'End Sub
-------------------------------
# RaisePostBackEvent メソッドより前でText値が書き変わってる!?

[追記]ソースの一部を削除

[ メッセージ編集済み 編集者: えんぞ@見習 編集日時 2004-12-18 16:48 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-12-21 21:43
引用:

kei69さんの書き込み(2004-12-18 11:10)より:

1. 動的にテキストボックスを作成する。(Page_Loadイベント時)


 Loadイベントハンドラで作成するのはやめましょう。生成はページの初期化処理イベントハンドラであるPage_initで行いましょう。
Visual C# .NET を使用して ASP.NET で動的にコントロールを作成する方法

 で、「[PRB] EnableViewState が False に設定されていてもサーバー コントロールの状態が維持される」は、「ViewStateをfalseにしても、内容が保持される」であって、プログラム内の変更が反映されない、というのとはちょっと違いますよね。つまり、

1.CheckBoxのSaveViewStateをFalseにする
2.Not IsPostBack で、CheckBoxコントロールの背景色を Tomato にする
3.クライアントで Tomato で表示される
4.クライアントで「チェック」する
5.クライアントでPostする
6.サーバで処理される
7.再読込後、背景色は保持されていない、がチェックはされたまま

という現象が発生し、「PostBack前後で保持されないはずのデータ(チェック状態)が保持された」と。おそらく、kei69さんの内容は、SaveViewStateの設定に関係なく発生すると思います。

 それで、1年半以上前のことなので少々不安ですが、私の経験では、Loadイベントハンドラで追加したコントロールに対しては、PostBackによるイベントが発生しなかったと思うのです。「コントロール実行の有効期間」というトピックに、イベントやコールされるメソッドの順番が書かれていますが、InitイベントはLoadViewStateやLoadPostDataよりも前に発生します。Loadイベントはその後に発生します。LoadイベントではPostDataの読み込みがすんでいますから、ここで値を変えると、ユーザが変更した値を上書きで変更したことになり、イベントがキャンセルされたように思います。
 もちろん、WindowsアプリケーションではChangedイベントはプログラム中から変更しても発生します。ただし、ここで問題になるのは、“Changedイベントが発生する要因”です。
 Changedイベントは、ある値が別の値に変更されるから発生します。では、ページ要求ごとに新しいオブジェクトを作成するWebアプリケーションにとって、“変更前の値”とはなんでしょう?これがViewStateにある、“送信前の値”になります。では、“送信前の値”と、“受信した値”が違っているというのを、どこで判断するのでしょう?Windowsアプリケーションでは、セットアクセサの先頭または最後にOn〜Changeメソッドの呼び出しがコーディングされているようです。WebアプリケーションではIPostBackDataHandler.LoadPostDataメソッドで行うようです。このメソッドで判定した後、実際にイベントが励起されるのは、IPostBackDataHandler.RaisePostBackEventメソッドです。「コントロール実行の有効期間」を見るとわかるとおり、Pageオブジェクトがこの2つのメソッドを呼び出す間に、Loadイベントが発生します。もし、Loadイベントハンドラでデータを変更してしまうと、LoadPostDataメソッドで判定した内容が覆ってしまいます。

 私は「Loadイベントハンドラ内に書かれている『ページを初期化するユーザー コードをここに挿入します。』というコメントはバグだ」と考えていますが、Loadイベントまでを“初期化処理”と考えると、このコメントも正しいと言えます。つまり、Windowsアプリケーションでたとえると、Loadイベントが完了した状態が、Windowsフォームの表示が完了した状態である、と。しかし、それぞれのメソッドで“初期化される値”の意味を考えて、「どこで初期化するべきか」をよく考えなければならないでしょう。
 そうすると、まずコントロールの追加は、やはりInitイベントで行うべきです。次にそこで追加したコントロールに対する値の変更は、Windowsアプリケーションと照らし合わせても“初期化処理”で行うべきではありません。Loadイベント終了後、IPostBackDataHandler.RaisePostBackEventメソッド以降に行うべきでしょう。

_________________
1

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