我一直试图解决这些问题。在asp gridview中使用外键创建数据绑定时,然后编辑一行并更改dropbox中的外键,保存更改并返回到查看模式(编辑行= -1),该值在国外关键列消失(除非它没有改变)。但是,如果刷新页面(不再发送数据),则会正确显示值,并按预期更改。
这也发生在继承自asp网格视图的SPGridView(sharepoint网格视图)中。
让我向您展示一个仅使用更新方法的简化示例: (我希望它不会太简化)
网格
<asp:GridView
ID="exampleGridView"
runat="server"
DataKeyNames="Id"
AutoGenerateColumns="false"
OnRowUpdating="UpdateClick"
OnRowDataBound="RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Id">
<ItemTemplate>
<asp:Label ID="Id" runat="server" Text='<%# Bind("Id") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Login">
<ItemTemplate>
<asp:Label ID="Login" runat="server" Text='<%# Bind("Login") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="EditLoginTextBox" runat="server" Text='<%# Bind("Login") %>' Enabled="false" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Role">
<ItemTemplate>
<asp:Label ID="Role" runat="server" Text='<%# Bind("Role.Title") %>' />
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="EditRoleDropDownList" runat="server" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:LinkButton ID="EditLinkBtn" runat="server" CommandName="Edit" Text="edit" />
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="UpdateLinkBtn" runat="server" CommandName="Update" Text="update" />
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
背后的代码
protected void UpdateClick(object sender, System.Web.UI.WebControls.GridViewUpdateEventArgs e)
{
// context taken from constructor, created at the beginning of a request and disposed at the end of a request
User user = this.ctx.Users.First(u => u.Id == id);
GridViewRow row = this.exampleGridView.Rows[e.RowIndex];
user.Login = ((TextBox)row.FindControl("EditLoginTextBox")).Text;
int roleId =int.Parse(((DropDownList)row.FindControl("EditRoleDropDownList")).SelectedValue);
if (user.Role.Id != roleId)
{
user.Role = ctx.Attach(new Role
{
Id = roleId
});
}
this.ctx.SaveChanges();
this.exampleGridView.EditIndex = -1;
this.BindGrid();
}
protected void RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow &&
(e.Row.RowState & DataControlRowState.Edit) == DataControlRowState.Edit)
{
var user = (User)e.Row.DataItem;
var editRoleDropDownList = (DropDownList)e.Row.FindControl("EditRoleDropDownList");
this.BindRoleDropDownList(editRoleDropDownList);
editRoleDropDownList.SelectedValue = user.Role.Id.ToString();
}
}
private void BindGrid()
{
this.exampleGridView.DataSource = this.ctx.Users.Include(u => u.Role);
this.exampleGridView.DataBind();
}
private void BindRoleDropDownList(DropDownList roleDropDownList)
{
// list of roles
if (this.cachedRoles == null)
{
this.cachedRoles = this.ctx.Roles.ToList();
}
roleDropDownList.DataSource = this.cachedRoles;
roleDropDownList.DataValueField = "Id";
roleDropDownList.DataTextField = "Name";
roleDropDownList.DataBind();
}
答案 0 :(得分:0)
答案比我想象的要简单。问题在于Update方法:
int roleId = int.Parse(((DropDownList)row.FindControl("EditRoleDropDownList")).SelectedValue);
if (user.Role.Id != roleId)
{
// this is the problem
user.Role = ctx.Attach(new Role
{
Id = roleId
});
}
问题是我用这个新对象覆盖角色,其中Role.Title显然等于空字符串。物体停留在那里。所以正确的解决方案如下:
int roleId = int.Parse(((DropDownList)row.FindControl("EditRoleDropDownList")).SelectedValue);
if (user.Role.Id != roleId)
{
user.Role = this.ctx.Roles.First(r => r.Id == roleId);
}