ASP.Net GridView - Update Row Command does not revert back to display-only
I have a GridView that is populated from a LinqDataSource. When I update a row, the RowCommand fires and the change is persisted to the database, but the Grid does not refresh. I have it in an UpdatePanel and explicitely call Update() in the RowCommand handler, but there is no postback and the page just sits there in Edit mode. Once I click cancel, it will return to view-only and the grid shows the new value.
My suspicion is that something in the wiring of the GridView regarding the data source is wrong. No exception bubbles up, though. A stripped-down copy of the markup is below. Any ideas?
<asp:UpdatePanel ID="uPanel" runat="server" UpdateMode="Conditional"
EnableViewState="true" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:LinqDataSource ID="YieldDataSource" runat="server"
ContextTypeName="myhDataContext" TableName="vw_drug_yields"
OnSelecting="YieldDataSource_Selecting" EnableUpdate="true" />
<asp:GridView ID="YieldGridView" runat="server" Width="900px"
OnRowDataBound="editG开发者_如何学Pythonrid_RowDataBound"
DataSourceID="YieldDataSource" EnableViewState="true"
OnRowCommand="YieldGridView_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Net Fill" ItemStyle-HorizontalAlign="Center">
<ItemTemplate><%# DataBinder.Eval(Container.DataItem, "net_fill") %>
</ItemTemplate>
<EditItemTemplate><asp:TextBox ID="tbNetFill" runat="server"
Text='<%# DataBinder.Eval(Container.DataItem, "net_fill") %>' >
</asp:TextBox></EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False" ItemStyle-Width="40px">
<ItemTemplate>
<asp:ImageButton CommandName="Edit" ID="btnEdit" SkinID="btnEdit"
runat="server" ToolTip="Edit" CausesValidation="false"/>
</ItemTemplate>
<EditItemTemplate>
<asp:ImageButton CommandName="Update" ID="btnSubmit" SkinID="btnSubmit"
runat="server" ToolTip="Save" CausesValidation="true"
CommandArgument="<%# ((GridViewRow) Container).DataItemIndex %>" />
<asp:ImageButton CommandName="Cancel" ID="btnCancel" SkinID="btnCancel"
runat="server" ToolTip="Cancel" CausesValidation="false"/>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView></ContentTemplate></asp:UpdatePanel>
The handler:
protected void YieldGridView_RowCommand(Object sender,
GridViewCommandEventArgs e) {
if (e.CommandName == "Update") {
try {
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow gdrow = YieldGridView.Rows[index];
// do some validation and handle update
db.SubmitChanges();
YieldGridView.DataBind();
uPanel.Update();
}
catch (Exception ex) {
ShowError(this, "Error while updating yields", ex, true);
}
}
After removing the UpdatePanel and turning off callbacks for the GridView, I received the following error when clicking the Update button:
Could not find a row that matches the given keys in the original values stored in ViewState. Ensure that the 'keys' dictionary contains unique key values that correspond to a row returned from the previous Select operation.
The problem is that there is no single unique key for this data, as it is dynamically assembled from different sources. It should not be needed, but it seems that a GridView with LinqDataSource can't function without it. In addition, I am populating the grid from a View, which does not have a primary key. The solution involved 3 changes:
- disabling updates for the LinqDataSource
- changing the command name from Update to MyUpdate (so that Linq does not try to auto-wire it)
- setting the YieldGridView.EditIndex = -1 prior to calling Update on the UpdatePanel
Thanks for your help.
Before you call Update(), call GridView.DataBind() to rebind against the LINQDataSource control.
try this:
YieldGridView.DataBind();
//though this seems useless after call to DataBind, but lets just try :)
YieldGridView.EditIndex = -1;
uPanel.Update();
精彩评论