【问题标题】:When exactly does the OnItemUpdated event fire specifically in a FormView in ASP.NET?OnItemUpdated 事件究竟何时在 ASP.NET 的 FormView 中专门触发?
【发布时间】:2013-04-12 22:05:31
【问题描述】:

我一生都无法弄清楚 OnItemUpdated 何时被解雇。我一直在尝试学习 ASP.NET,所以你在这段代码中看到的一些东西可能是故意用困难的方式完成的(这样我可以更好地理解幕后发生的事情)

基本上,我有一个 GridView,它是使用表单视图作为细节的主控件。

这是GridViewSelectedIndexChanged 方法

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的属性可以看出我指定了OnItemUpdatingOnItemUpdated

这里是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 吗?

【问题讨论】:

标签: c# asp.net .net event-handling webforms


【解决方案1】:

结论:

查看FormView类的源代码似乎使用DataBinding时没有触发ItemUpdated事件。

只有在设置FormViewSelectMethodUpdateMethodDeleteMethodInsertMethod 属性时才会触发ItemUpdated 事件。

证据

当您更新 FormView 中的项目时,会调用其内部调用 HandleUpdate 的“UpdateItem”方法。

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;

随后在dataSourceView 上调用Update

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

我们可以看到,Update 方法的最后一个参数接受了一个回调,在本例中为HandleUpdateCallbackHandleUpdateCallback 是我们的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;

此属性IsDataBindingAutomaticBaseDataBound 类的内部属性(从我们的FormView 类更上一层的基类位):

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

由于我们没有使用DataSourceID,我们最终返回了IsUsingModelBinders 的值。这是BaseDataBoundControl 上的一个虚拟属性,它在CompositeDataBoundControl 类中被覆盖,这是我们的FormView 直接继承的基类。

现在我们来看看直接决定我们的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

因为这是错误的,我们之前两次奇怪的代码只是简单地返回并且永远不会到达触发 ItemUpdated 事件的代码部分。

【讨论】:

    猜你喜欢
    • 2010-10-23
    • 1970-01-01
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-10
    相关资源
    最近更新 更多