我不知道OnItemUpdated何时被解雇。我一直在搞乱ASP。. NET试图学习它,所以你在这段代码中看到的一些东西可能是故意用困难的方式完成的(所以我可以更好地理解幕后发生的事情)
基本上,我有一个GridView,它是使用formview作为detail的主控件。
这是GridView
SelectedIndexChanged
方法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?
结论:
查看FormView
类的源代码,似乎ItemUpdated
事件在使用DataBinding时不会触发。
ItemUpdated
事件只有当你设置FormView
的SelectMethod
、UpdateMethod
、DeleteMethod
或InsertMethod
属性时才会被触发。
证明
当你在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;
随后在dataSourceView
上调用Update
。
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;
}
}
由于我们没有使用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
。