views:

2213

answers:

3

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="editGrid_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);
      }
  }
A: 

Hey,

Before you call Update(), call GridView.DataBind() to rebind against the LINQDataSource control.

Brian
I just added the code-behind. This is what I am doing.
cdonner
Odd then... try this, put a breakpoint on the db.SubmitChanges() method call. Before you step over it and run it, check db.GetChangeSet() in the immediate window, and see if there are any inserts, updates, or deletes. The change set is the way to figure out what's changing. See if any updates are queued.
Brian
I am not using the GridView's update mechanism, so I don't care much if there is change set. I get the rowindex in my method, pull the data that I need from the row, and then run the Linq query to update the row.
cdonner
My point was the change set would let you know if your pulling and running the LINQ query is even signaling to the context that you are updating the row... it's possible it is not...
Brian
Sorry, I misunderstood. The Linq query updates fine. The problem is that the UpdatePanel does not refresh the GridView (or the GridView itself - I am not even sure if the UpdatePanel is needed). There is no Postback after the command handler finishes, and the Grid remains in Edit mode.
cdonner
A: 

try this:

YieldGridView.DataBind();
//though this seems useless after call to DataBind, but lets just try :)
YieldGridView.EditIndex = -1;
uPanel.Update();
TheVillageIdiot
Ha, this was one of the things I tried before posting here - to no avail.
cdonner
Like I said, there is no postback, so no matter what I do, it does not refresh. But the code fully executes and there are no exceptions (that I can see).
cdonner
A: 

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.

cdonner