0

So, this is my scenario

I have this gridview, inside a custom control. Each row element of this grid can be opened in a separate popup window to edit its details (yes, a popup window, its the way the client wants it)

So, to edit and retrieve this row edited data, I store it in a Session variable to show the details on the popup window and later

    ObjectType editObject = CurrentDS.FirstOrDeafult(o => o.Index == e.CommandArgument);
     Session["EditObjectVar"] = editObject;
     ScriptManager.RegisterStartupScript(this.Page, typeof(string), "OPEN_WINDOW", "window.open('ObjDetails.aspx', '_blank','scrollbars=yes,status=yes,toolbar=no,menubar=no,location=no,resizable=1,width=700,height=425,center=yes' );", true);

When closing and saving the changes, I store once again on the same Session variable, and force a postback on the parent window as to refresh the data.

   Session.Remove("EditObjectVar");
    StoreValuesOnObject();
    Session["EditObjectVar"] = editObject;
    ScriptManager.RegisterStartupScript(this.Page, GetType(), "Close Popup", "window.opener.__doPostBack();window.close();", true);

On the controls page_load event, I check if there's a postback and the Session variable has data and I need to refresh the object on the DS and the gridview.

if (Page.IsPostBack && Session["EditObjectVar"] != null)
{
    ObjectType modObj = (ContainerType) Session["EditObjectVar"];
    ObjectType oldObj = CurrentDS.FirstOrDeafult(o => o.Index == modObj .Index);
    CurrentDS.Remove(oldObj);
    CurrentDS.Add(modObj);
    gv.DataSource = null;
    gv.DataSource = CurrentDS;
    gv.DataBind();
    Session.Remove("EditObjectVar");
}

Everything is persisted correctly, I retrieve the edited object, more so, given that on the Session variable, more than storing the object, the object memory location is stored, meaning that, by the forced postback, the edited object is already updated on the grid datasource (which, is also stored on a Session variable), so I bind the gridview to the updated DS, with the updated object, but still, the gridview is no refreshed, its still retrieving the rows state from the viewstate

Any idea how I can accomplish my task? Update panel is an option, I know, but I don't have greenlight to use them

I already have something similar, the object details, also contains a collection of object that are shown on a gridview in the details popup, and as its parent, the user also can open the detail of the child object in a separate popup window. The logic described before applies here, but with the object details, the object child objects gridview is refreshed correctly!

Edited: Added as much code as I could to explain better, given that I'm under a very strong confidential agreement, and posting real code online can give some troubles, but I'm already out of ideas

Edit 2: Forgot to add the .DataBind() on the example, but it is in the code

Edit 3: Forgot to mention that, the GridView that it's not refreshing, has controls as to be able to change some values directly on the gridview. This is the html of the gridview

    <asp:GridView ID="gv" runat="server" ShowHeader="false" CellPadding="5" CellSpacing="0" EnableViewState="true" AutoGenerateColumns="False" OnRowCreated="RowCreated" 
    OnRowDataBound="RowDataBound"  GridLines="Both" BorderStyle="Solid" BorderColor="Black" BorderWidth="1px">
    <Columns>

     <asp:TemplateField>
            <ItemTemplate>
               <asp:ImageButton ID="imgDelete" runat="server"   CausesValidation="false"  AlternateText="Delete Part"
                     CommandName="cnt_delete" CommandArgument='<%# Eval("ContainerIndex") %>'  OnClick="imgDelete_Click"
                    ImageUrl="~/img/del.png" />
               <asp:ImageButton ID="imgDetails" runat="server"   CausesValidation="false"  AlternateText="View Cnt Details"
                     CommandName="cnt_details" CommandArgument='<%# Eval("ContainerIndex") %>'
                    ImageUrl="~/img/edit_icon.png" Height="15px" onclick="imgDetails_Click" />
                <asp:Label ID="lblNum" runat="server"  Text='<%# Eval("ContainerIndex") %>' ></asp:Label>
            </ItemTemplate>
            <ItemStyle  CssClass="subGridItem" VerticalAlign="Top" />
        </asp:TemplateField>        
     <asp:TemplateField>
            <ItemTemplate>
                <table style="FONT-SIZE: xx-small; FONT-FAMILY: Verdana; background-color:#F5F5F5" cellspacing="1" cellpadding="1"
            border="0" width="100%" >           
            <tr>                                            

                <td>
                      <asp:Label ID="lblQty" runat="server" Text="Qty" ></asp:Label>
                      <asp:Label ID="lblQtyRq" runat="server"  Text="*"></asp:Label>
                </td>
                    <td style="white-space:nowrap">
                     <asp:Label ID="lblWeight" runat="server" Text="Weight" ></asp:Label>
                     <asp:Label ID="lblWeightRq" runat="server"  Text="*"></asp:Label>
                </td>       
                <td style="white-space:nowrap">
                     <asp:Label ID="lblCntType" runat="server" Text="Container Type" ></asp:Label>
                     <asp:Label ID="lblCntTypeRq" runat="server"  Text="*"></asp:Label> 
                </td>

            </tr>
            <tr valign="top">           

            <td><asp:TextBox ID="txtQty"  Width="50px" runat="server" CssClass="detailsInput" Text='<%# Eval("Quantity") %>' MaxLength="7" ></asp:TextBox><br />
                <asp:RequiredFieldValidator ID="validatorQty" runat="server" ControlToValidate="txtQty" Display="Dynamic" ErrorMessage="Required" ></asp:RequiredFieldValidator>
                <asp:CompareValidator ID="CompareQty" runat="server"  Display="Dynamic" ControlToValidate="txtQty" Operator="GreaterThan" ValueToCompare="0" Type="Double"  ErrorMessage="invalid"></asp:CompareValidator>  
           </td>
                <td><asp:TextBox ID="txtWeight" Width="50px" runat="server" CssClass="detailsInput" Text='<%# Eval("Weight") %>' MaxLength="11" ></asp:TextBox><br />
                <asp:RequiredFieldValidator ID="ValidatorWgt" runat="server" ControlToValidate="txtWeight" Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
                <asp:CompareValidator ID="CompareWeight" runat="server" Display="Dynamic" ControlToValidate="txtWeight" Operator="GreaterThan" ValueToCompare="0" Type="Double"  ErrorMessage="invalid"></asp:CompareValidator>
            </td>
            <td>
                <asp:DropDownList ID="lstCntTypes" runat="server"  ></asp:DropDownList><br />
                <asp:RequiredFieldValidator ID="validatorCntTypes" runat="server" CssClass="TPValidator" ControlToValidate="lstCntTypes" Display="Dynamic" ErrorMessage="Required"></asp:RequiredFieldValidator>
            </td>
            </tr>
            <tr><td colspan="12">
            <table width="100%" >
            <tr>                
                <td style="white-space:nowrap">
                    <asp:label id="lblProperShippingName" CssClass="TPLabel"  Runat="server" Visible="false">Proper shipping name</asp:label>
                    <asp:label id="lblProperShippingNameM" Runat="server" ForeColor="red" Font-Size="xx-small" Visible="false">*</asp:label></td>
                <td style="white-space:nowrap">
                    <asp:label id="lblHazClass" CssClass="TPLabel"  Runat="server" Font-Size="xx-small" Visible="false">Hazard class</asp:label>
                    <asp:label id="lblHazClassM" Font-Bold="true" Runat="server" ForeColor="red" Font-Size="xx-small" Visible="false">*</asp:label>
                </td>               
                <td style="white-space:nowrap">
                    <asp:label id="lblUNNumber" CssClass="TPLabel"  Runat="server" Visible="false" >UN/NA Identification Number</asp:label>
                    <asp:label id="lblUNNumberM" Runat="server" ForeColor="red" Font-Size="xx-small" Visible="false">*</asp:label>
                </td>
                <td style="white-space:nowrap">
                    <asp:label id="lblPackGroup" CssClass="TPLabel"  Runat="server" Visible="false" >Packing group</asp:label>
                    <asp:label id="lblPackGroupM" Font-Bold="true" Runat="server" ForeColor="red" Visible="false" >*</asp:label>
                </td>
                <td>
                    <asp:label id="lblIMO" CssClass="TPLabel"  Runat="server" Visible="False">IMO Classification</asp:label></td>
                <td><asp:label id="lblTunnel" CssClass="TPLabel" Runat="server" Visible="False">Tunnel Restriction</asp:label></td>
            </tr>
            </table>
           </td>        </tr>
        <tr>
        <td colspan="8">   </td></tr>
        </table>
            </ItemTemplate>
      <ItemStyle VerticalAlign="Top" />     
        </asp:TemplateField>  
    </Columns>
</asp:GridView>

As you can notice here, both the txt inputs are getting their values form the eval of the row propertie, but the lst doesn't. the lst value is set on the RowDataBound event, I can see the modified value there, but its still showing the one taken from the viewstate

CJLopez
  • 5,495
  • 2
  • 18
  • 30
  • I hope no one ever greenlights you to use UpdatePanels. They're much more trouble than they're worth. Anyways, you should post your code and show where you're trying to update the GV with the new information. Create a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve). – mason Feb 13 '15 at 19:30
  • @mason So, what could I use, If I wanted AJAX like functionality on a project that needs to use stock controls. I have worked previously using DevExpress controls, and its amazingly easy to do callback with their controls, but like with this client, who only want stock control, how could I go with? Several other pages already use update panels – CJLopez Feb 13 '15 at 19:51
  • AJAX! No seriously, you're much better off using AJAX directly (perhaps with the assistance of a helper library such as [jQuery AJAX](http://api.jquery.com/jquery.ajax/)) than using UpdatePanel's inefficient abstraction. On the server side, either [ASP.NET Web API](http://www.asp.net/web-api) or WCF for responding to the AJAX calls (don't use web/page methods!). For stocks, [SignalR](http://www.asp.net/signalr) might be appropriate in some cases too. Also see [How to implement real time data for a web page](http://stackoverflow.com/questions/25829343). – mason Feb 13 '15 at 19:55
  • mason thanks, I was certain you might mention stock AJAX like the JQUERY one, I'm also more fond of programming pure html5/jquery/js/css pages rather than asp.net web forms and adding some rest/wcf for server side. Hell, i cringe each time I'm told to create webforms instead of MVC this days! – CJLopez Feb 13 '15 at 19:58

2 Answers2

0

I didn't try to track everything, but it isn't because you left out the "gv.DataBind();" in there, is it? I know that can happen when you switch back and forth from PC apps to Web apps...

Steve
  • 531
  • 5
  • 16
0

So, I was finally to get around to this and have it working.

In the end, I set up a button on the same custom control where the grid is, and have this control retrieve the info that it's on Session and refresh the grid, not do it on the call back

Edit: This button its hidden from the eyes of the user by css (display: none). Not very fancy way to do it, but, it works

So, when retrieving the object to edit, I also store in Session the UniqueID of the button that refreshes the DS

 ObjectType editObject = CurrentDS.FirstOrDeafult(o => o.Index == e.CommandArgument);
     Session["EditObjectVar"] = editObject;
     Session["BtnRefreshUniqueID"] = btnRefreshDS.UniqueID;
     ScriptManager.RegisterStartupScript(this.Page, typeof(string), "OPEN_WINDOW", "window.open('ObjDetails.aspx', '_blank','scrollbars=yes,status=yes,toolbar=no,menubar=no,location=no,resizable=1,width=700,height=425,center=yes' );", true);

And when I'm about to store and close the details popup, I set up the postback that will refresh the DS calling the btnRefreshDS OnClick Event

    Session.Remove("EditObjectVar");
    StoreValuesOnObject();
    Session["EditObjectVar"] = editObject;
    ScriptManager.RegisterStartupScript(this.Page, GetType(), "Close Popup", String.Format("window.opener.__doPostBack('{0}', 'OnClick');window.close();", Session["BtnRefreshUniqueID"].ToString()), true);

And, this is the OnClick event

protected void btnRefresDS_Click(object sender, EventArgs e)
{
    try
    { 
        if (Session["EditObjectVar"] != null)
        {
            gv.DataSource = CurrentDS;
            gv.DataBind();
            Session.Remove("EditObjectVar");
        }
    }
    catch (Exception ee)
    {
        MyPage.Log(ee.StackTrace);
        MyPage.Log(ee.Message);
    }
}

Given that, on the Session variable its stored the object memory location as instead of the object per se, I already have the updated object on my DS (which is also stored on Session) so I only need to asign the DS and call the databind.

Hope this help anyone!

CJLopez
  • 5,495
  • 2
  • 18
  • 30
  • If, your server is using SQL SessionState instead of ad-hoc, this will not DO! Learnt that the hard way. You will need to adjust the DS to either update the modified object or remove the old one and store the new. Then you databind the data. – CJLopez Aug 06 '15 at 17:15