1

OnItemUpdated がいつ起動されるかは、一生わかりません。私はそれを学ぼうとして ASP.NET をいじっていました。そのため、このコードで見られるいくつかのことは、意図的に難しい方法で行われている可能性があります (舞台裏で何が起こっているのかをよりよく理解できるようにするため)。

基本的に、フォームビューを詳細として使用するマスター コントロールである GridView があります。

ここにSelectedIndexChanged方法がありますGridView

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
    var context = new DataAccessLayer.SafetyEntities();
    var se = (from c in context.Employees
                  where c.EID == (long)GridView1.SelectedDataKey.Value
                  select c).ToList();
    FormView1.DataSource = se;
    FormView1.DataKeyNames = new string[] { "EID" };
    FormView1.DataBind();
}

それはうまく機能しています。選択した詳細が編集用のフォームに表示されます。これはformview次のようになります。

<asp:FormView ID="FormView1" runat="server" DefaultMode="Edit" OnItemUpdating = "FormView1_ItemUpdating" OnItemUpdated="BLAH">
    <ItemTemplate>
        Select an employee!
     </ItemTemplate>
     <EditItemTemplate>
         <table>
             <tr>
                 <th>Name: 
                 </th>
                    <td>
                        <asp:TextBox runat="server" ID ="NameEdit" Text='<%#Bind("Name") %>' /> 
                    </td>
                    <br />
            </tr>
            <tr>
                <th>Manager: 
                </th>
                <td>
                    <asp:DropDownList ID = "DDLEdit1" DataSourceID = "ManagerEntitySource" runat="server"
                           DataTextField = "Option_Value" DataValueField = "Option_Value"
                           SelectedValue = '<%#Bind("Manager") %>'  
                           AppendDataBoundItems="true">
                    </asp:DropDownList> 
                </td>
                <br />
            </tr>
            <tr>
                <th>Location: 
                </th>
                <td>
                    <asp:DropDownList ID="DDLEdit2" DataSourceID = "LocationEntitySource" runat="server"
                           DataTextField = "Option_Value" DataValueField = "Option_Value"
                           SelectedValue='<%#Bind("Building") %>' 
                           AppendDataBoundItems="true">
                    </asp:DropDownList>
                </td>
                <br />
        </table>
        <asp:Button ID="Button2" Text="Submit Changes" runat="server" CommandName="Update" />
            <!--<asp:LinkButton ID = "LB1" Text="Update" CommandName="Update" runat="server" /> -->
    </EditItemTemplate>       
</asp:FormView>

これも同様に機能します。FormView私が指定OnItemUpdatingした との属性からわかりますOnItemUpdated

ここにあるOnItemUpdating

protected void FormView1_ItemUpdating(object source, FormViewUpdateEventArgs e)
{
   DebugBox.Text = FormView1.DataKey.Value.ToString();
   DataAccessLayer.SafetyEntities se = new DataAccessLayer.SafetyEntities();
   var key = Convert.ToInt32(FormView1.DataKey.Value.ToString());
   DataAccessLayer.Employee employeeToUpdate = se.Employees.Where(emp => emp.EID == key).First();
   employeeToUpdate.Name = e.NewValues["Name"].ToString();
   employeeToUpdate.Manager = e.NewValues["Manager"].ToString();
   employeeToUpdate.Building = e.NewValues["Building"].ToString();
   se.SaveChanges();
   GridView1.DataBind();

}

これもうまくいきます。アイテムは適切に更新されており、GridViewさわやかです。

ここにあるOnItemUpdated

protected void BLAH(object source, FormViewUpdatedEventArgs e)
{
    DebugBox2.Text = "BLAH!!!!";
}

そして、ここに問題があります。これは決して呼び出されません!このイベントを発生させるための手順がどこかに欠けていますか? ボタンが Command="Update" を呼び出し、ItemUpdating を起動してから ItemUpdated を起動することを理解していると思いました。間違いなく ItemUpdating を呼び出していますが、それだけです。ItemUpdated を起動するには何か追加が必要ですか?

4

1 に答える 1

5

結論:

FormViewクラスのソース コードを見ると、ItemUpdatedDataBinding を使用するとイベントが発生しないようです。

このイベントは、 の、、またはプロパティをItemUpdated設定した場合にのみ発生します。SelectMethodUpdateMethodDeleteMethodInsertMethodFormView

の証拠

アイテムを更新すると、FormViewその「UpdateItem」メソッドが呼び出され、内部的に が呼び出されますHandleUpdate

public virtual void UpdateItem(bool causesValidation)
    {
      this.ResetModelValidationGroup(causesValidation, string.Empty);
      this.HandleUpdate(string.Empty, causesValidation);
    }

private void HandleUpdate(string commandArg, bool causesValidation)
    {
       // Lots of work is done here
    }

HandleUpdateメソッドの最後で、OnItemUpdatingイベントがトリガーされます。

this.OnItemUpdating(e);

その後に、かなり奇妙なコード行が続きます。

if (e.Cancel || !bindingAutomatic)
          return;

Updateこれに続いて、 への呼び出しが続きdataSourceViewます。

dataSourceView.Update((IDictionary) e.Keys, (IDictionary) e.NewValues, 
(IDictionary) e.OldValues, 
new DataSourceViewOperationCallback(this.HandleUpdateCallback));

Update メソッドの最後のパラメーターがコールバックを受け取ることがわかります。この場合はHandleUpdateCallbackです。イベントが最終的にトリガーHandleUpdateCallbackされる場所です。OnItemUpdated

private bool HandleUpdateCallback(int affectedRows, Exception ex)
    {
      FormViewUpdatedEventArgs e1 = new FormViewUpdatedEventArgs(
                                                       affectedRows, ex);
      e1.SetOldValues(this._updateOldValues);
      e1.SetNewValues(this._updateNewValues);
      e1.SetKeys(this._updateKeys);
      this.OnItemUpdated(e1);
      // A lot of other stuff goes on here
     }

これが実行中のメソッドに最終的にたどり着くまでの地図ですがOnItemUpdated、この場合はなぜ実行されないのでしょうか?

少し前に戻って、HandleUpdate先ほど述べたメソッドの「興味深い」部分に戻りましょう。

if (e.Cancel || !bindingAutomatic)
          return;

何が起きてる?イベントをキャンセルするわけではありませんが!bindingAutomatic、そこで何が起こっているのでしょうか?

値はHandleUpdateメソッドのさらに上に設定されます。

bool bindingAutomatic = this.IsDataBindingAutomatic;

このプロパティ はIsDataBindingAutomatic、クラスの内部プロパティですBaseDataBound(基本クラスは、クラスのチェーンより少し上にありますFormView)。

  protected internal bool IsDataBindingAutomatic
    {
      get
      {
        if (!this.IsBoundUsingDataSourceID)
          return this.IsUsingModelBinders;
        else
          return true;
      }
    }

a を使用していないため、DataSourceID最終的に の値を返しますIsUsingModelBinders。これは、直接継承する基本クラスでBaseDataBoundControlあるクラスでオーバーライドされるの仮想プロパティです。CompositeDataBoundControlFormView

ここで、OnItemUpdatingメソッドが起動されるかどうかを直接決定するコードのビットに到達します。

protected override bool IsUsingModelBinders
    {
      get
      {
        if (string.IsNullOrEmpty(this.SelectMethod) 
            && string.IsNullOrEmpty(this.UpdateMethod) 
            && string.IsNullOrEmpty(this.DeleteMethod))
          return !string.IsNullOrEmpty(this.InsertMethod);
        else
          return true;
      }
    }

これは基本的に、SelectMethod、UpdateMethod、または DeleteMethod (これらは FormView の文字列プロパティ) を設定した場合は true を返し、それ以外の場合は InsertMethod を設定したかどうかを教えてくれるということです。この場合、これらのプロパティを設定していないため、戻り値はfalseです。

これは false であるため、前の 2 回からのコードの興味深い部分は単純に返され、ItemUpdated イベントをトリガーするコードの部分に到達することはありません。

于 2013-04-13T18:16:23.880 に答える