2004.11.12

ASP.netの Webフォームコントロールの値保持について

ASP.net には ViewState という機能がある。
この ViewState というものが裏(Framework)で勝手にいろいろとやっていてくれるおかげで
例えば、ASPの時代には必要だった、画面再表示時のラジオボタンのグループの選択とか
リストボックスの内容一覧をプログラムで設定する作業が省力化された。
非常に便利な機能で ASP.net のひとつのウリだと思う。

ただし、ViewState は、基本的に自動で使われるような設定になっているのだが、
知らず知らずのうちに使いすぎていると ViewStateを覚えておくために使われている
画面の隠し項目 __VIEWSTATE の値がやたらと増え、
場合によってはこの ViewState のためだけに画面全体の表示/更新が遅くなったりする。

ViewState は使わなくても良い場合があることに常に意識しておく必要がある。
これは雑誌にしろネット上の情報にしろよく言われていることだ。


では、その判断基準はどこにあるのだろうか。
まず、コントロール単位で ViewState を使用しない宣言をする EnableViewState= false
にしていた場合、基本的には初期値(デザイン時の設定)に戻る。
ただし、戻らないで設定された値が残ったままになる項目もある。
それがWebフォームコントロールでいうところの以下。

  TextBox.Text
  CheckBox.Checked
  RadioButton.Checked (ただし GroupName を付けていた場合に限る。単独のものは消える)
  CheckBoxList.SelectedIndex
  RadioButtonList.SelectedIndex

つまり HTMLフォームに置き換えて考えたときの一般的な入力項目は基本的には残るようだ。
(ただし、これはもしかしたらブラウザに依存するものもあるかもしれない)

これに対して、以下のような Webフォーム専用の項目が初期化される。

  Label.Text
  CheckBox.Text
  RadioButtonList.Items
  DropDownList.Items
   等々・・・

 

さて、ここからが今回の本題なのだが、上記に加えて ViewState は CheckBoxList だけに
特殊な動作をする場合がある。
具体的には CheckBoxList を Enabled= false に設定していた場合、
EnableViewState= true にしていても値を保持してくれないのだ。
しかも不可解なことに、リスト内容は設定した値/もしくは初期値になるのだが、
チェックは『何も選択されない状態』となる(“選択”はデザイン時の初期値にも戻るわけではない)

CheckBoxList 以外のコントロールが Enabled= false でも選択値もリスト内容も保持してくれる
ことを思うと、この (ASP.net) framework の動作は相当怪しい。


なんとかするには、自分で逐次値を保存/再設定しなくてはいけない。例えば以下のように。
(うまくすれば、storeだけでできそうな気がするのだが)

  private void storeCheckboxListViewState ( string vsControlName )
  { /** CheckBoxList(Enabled= false)の ViewState保持のためコード **/
    string sCheckListViewState= "";
    foreach ( ListItem oItem in ((CheckBoxList)(this.FindControl(vsControlName))).Items )
    { if ( oItem.Selected ) { sCheckListViewState += "\t" + oItem.Value; } }
    if ( sCheckListViewState != "" ) { sCheckListViewState= sCheckListViewState.Substring(1); }
    this.ViewState.Add( vsControlName, sCheckListViewState );
  }

  private void restoreCheckboxListViewState ( string vsControlName )
  { /** CheckBoxList(Enabled= false)の ViewState保持のためコード **/
    string sCheckListViewState= "\t" + ((string)(this.ViewState[vsControlName])) + "\t";
    foreach ( ListItem oItem in ((CheckBoxList)(this.FindControl(vsControlName))).Items )
    { if ( 0 <= sCheckListViewState.IndexOf("\t" + oItem.Value + "\t") ) { oItem.Selected= true; } }
  }

しかし、どうなんだ、これは?

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

photo
ichikawa