現在オフラインです。再接続するためにインターネットの接続を待っています

[PRB] コントロール値を変更していないにもかかわらず Change イベントが発生する

この記事は、以前は次の ID で公開されていました: JP314809
現象
特定の状況において、コントロールを変更していないにもかかわらず、ASP.NET Web コントロールの Change イベントが発生します。
原因
DropDownList コントロールの SelectedIndexChanged イベントや TextBox コントロールの TextChanged イベントなど、一部のコントロールは、Change イベントの登録があるかどうかに応じてビューステートを使用します。この問題は、イベントのフック後にこれらのコントロールを動的に作成したときに発生します。

ASP.NET がブラウザにページを表示するとき、動的に作成されたコントロールには関連する Change イベントがありません。イベントが存在しないため、ASP.NET はビューステートを保存しません。これを "ビューステートの最適化" と呼びます。

ページがポストバックされてイベントがフックされると、ASP.NET はビューステートを探しますが、ビューステートは存在しません。この相違によって、コントロールが変更されていないにもかかわらず Change イベントが発生します。
解決方法
ASP.NET がページを表示する前に、動的に作成されたコントロールの Change イベントをフックするようにします。これにより、コントロールのビューステートが存在することが保証されます。
状況
この動作は仕様です。
詳細

現象の再現手順

Web フォームの作成

  1. 新しい Visual Basic ASP.NET アプリケーションを ChangeFired という名前で作成します。
  2. デザイナ モードで WebForm1 を開きます。DataList コントロール、Button コントロール、および DataSet コントロールを 1 つずつフォームにドラッグします。
  3. [データセットの追加] ダイアログ ボックスで [型指定のないデータセット] をクリックし、[OK] をクリックします。コントロールはすべてデフォルト名のままにしておきます。
  4. DataSet1 の Tables コレクションを編集します。Table1 という名前の新しいテーブルを追加します。
  5. Table1 の Columns コレクションを編集します。Column1 という名前の新しい列を追加します。
  6. [DataList1] をクリックし、DataSource プロパティを DataSet1 に変更します。
  7. [DataList1] を右クリックし、[テンプレートの編集] をポイントして、[項目テンプレート] をクリックします。DropDownList コントロールを ItemTemplate セクションにドラッグします。
  8. [DropDownList1] をクリックし、Items コレクションに 5 つのアイテムを追加します。これらのアイテムの Text プロパティと Value プロパティをそれぞれ、one、two、three、four、および five に設定します。
  9. DropDownList1 の AutoPostBack プロパティを true に設定します。
  10. DropDownList1 の DataBindings コレクションを編集します。SelectedIndex プロパティに次のようなカスタム連結式を追加します。
    DataBinder.Eval(Container, "DataItem.Column1")					
  11. HTML ビューに切り替えます。@ Page ディレクティブの trace 属性を次のように true に設定します。
    <%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" Inherits="ChangeFired.WebForm1" trace="true" %>					

コード ビハインド ファイルの追加

  1. WebForm1.aspx を右クリックし、[コードの表示] をクリックします。
  2. 次のコードを Page_Load イベントに追加します。
    DataSet1.Tables(0).Rows.Add(New Object() {"1"})DataSet1.Tables(0).Rows.Add(New Object() {"2"})DataSet1.Tables(0).Rows.Add(New Object() {"3"})DataSet1.Tables(0).Rows.Add(New Object() {"4"})If Not IsPostBack Then  DataBind()End IfDim objItem As DataListItemFor Each objItem In DataList1.Items  AddHandler CType(objItem.FindControl("DropDownList1"), _  DropDownList).SelectedIndexChanged, AddressOf DropDownList1_SelectedIndexChanged  If Not objItem.FindControl("DropDownList1") Is Nothing Then    Trace.Write("Added SelectedIndexChanged Handler")  End IfNext					
  3. 以下に示す、SelectedIndexChanged イベントを処理する新しい Sub プロシージャを Page_Load イベントの下に作成します。
    Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As System.Object, _ByVal e As System.EventArgs)  DataBind()  Trace.Write("SelectedIndexChanged, DataBind()")  'Uncomment the following code to resolve this problem.  'Dim objItem As DataListItem  'For Each objItem In DataList1.Items  '  AddHandler CType(objItem.FindControl("DropDownList1"), _  '  DropDownList).SelectedIndexChanged, AddressOf DropDownList1_SelectedIndexChanged  'NextEnd Sub					

サンプルの実行

  1. ページを実行します。コントロール ツリーのトレース情報で、動的に作成された DropDownList コントロールにビューステートがあることを確認します。

    これは、DataBind メソッドへの呼び出しによって DropDownList コントロールが動的に作成され、Page_Load イベントの DataBind 呼び出し後にイベント ハンドラをフックしたために発生します。コントロールにイベント ハンドラがあるため、ビューステートの最適化は実行されません。
  2. ページのボタンをクリックします。ポストバックが発生し、Page_Load イベントの中のコードのみが実行されることを確認します。イベント ハンドラがコントロールに関連付けられているため、DropDownList コントロールのビューステートが存在します。
  3. DropDownList コントロールのいずれかの値を変更します。ポストバックが発生することを確認してください。また、ASP.NET によって Page_Load イベントが発生し、DropDownList1_SelectedIndexChanged イベントが実行されることを確認します。
  4. DropDownList1_SelectedIndexChanged イベントで、再度 DataBind メソッドを呼び出して新しい DropDownList コントロールを作成します。

    これらの新しい DropDownList コントロールには SelectedIndexChanged イベントがフックされていないため、ASP.NET はビューステートの最適化を使用し、新しい DropDownList コントロールのビューステートを保存しません。
  5. コントロールのツリーのトレース情報を確認します。DropDownList コントロールにビューステートが存在しないことを確認してください。
  6. ページのボタンをクリックします。ポストバックが発生し、ASP.NET によって Page_Load イベントが実行されることを確認してください。SelectedIndexChanged イベントを DropDownList コントロールにフックしたため、ASP.NET はビューステートがコントロールに関連付けられているものと見なします。

    しかし、ビューステートが存在しないため、アイテムを選択していなくても ASP.NET によって SelectedIndexChanged イベントが発生します。

解決方法

この問題を解決するには、DropDownList1_SelectedIndexChanged イベントのコードからコメントを外して、新しく作成されたコントロールにイベント ハンドラがフックするようにします。
view state
プロパティ

文書番号:314809 - 最終更新日: 10/19/2005 08:22:02 - リビジョン: 2.6

Microsoft ASP.NET 1.1, Microsoft ASP.NET 1.0

  • kbdatabinding kbevent kbprb kbservercontrols kbstate kbwebforms KB314809
フィードバック
error="var m=document.createElement('meta');m.name='ms.dqp0';m.content='true';document.getElementsByTagName('head')[0].appendChild(m);" onload="var m=document.createElement('meta');m.name='ms.dqp0';m.content='false';document.getElementsByTagName('head')[0].appendChild(m);" src="http://c1.microsoft.com/c.gif?">