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

文書翻訳 文書翻訳
文書番号: 314809 - 対象製品
この記事は、以前は次の 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 If
    
    Dim objItem As DataListItem
    For 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 If
    Next
    					
  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
      'Next
    End 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 イベントのコードからコメントを外して、新しく作成されたコントロールにイベント ハンドラがフックするようにします。

プロパティ

文書番号: 314809 - 最終更新日: 2005年10月19日 - リビジョン: 2.6
この資料は以下の製品について記述したものです。
  • Microsoft ASP.NET 1.1
  • Microsoft ASP.NET 1.0
キーワード:?
kbdatabinding kbevent kbprb kbservercontrols kbstate kbwebforms KB314809
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com