views:

1807

answers:

6

I have an update panel in a cell for each row within a gridview. The user clicks a link button from this update panel to display (using window.open()) a popup. Action is taken in that popup that updates the data contained within the aforementioned update panel. I want to trigger an update only for that update panel when the popup is closed.

What is the best way to do this? I'm researching capturing the window.close event and somehow passing a value that indicates where the popup was called from and then calling a postback for that update panel in javascript. If it makes a difference (in the least it will - ugh - in my javascript code), I am using a master page and only coding for IE.

Found this: http://forums.asp.net/p/1166328/1941797.aspx which uses the window.opener.document... Again, using a master page complicates matters.

A: 

I have done this from a Flash application. My "hack" if you will was to hide a real ASP:Button with CSS. The button was inside the UpdatePanel. I passed the Button.ClientId to the external resource(Flash, new window...etc). When the external resource(Flash in my case) was finished, it calls a JavaScript function that accepts the ClientId and it calls .Click() on the button.

JavaScript:

function CallASPNETClick(id) {  
    var elmt = document.getElementById(id);   
    elmt.click();

}

Markup:

!--this is uses for capture an event from Flash with javascript, do not remove--->
<asp:Button ID="hiddenButton" runat="server" Text="Button" style="visibility:hidden" OnClick="hiddenButton_Click" />
rick schott
That's the path I've been going down. The trouble I've run into is adding the code for the OnClientClick in code behind that uses the id of the hidden button (I'm using a master page, so the id is prefixed with "ctl00_MasterContentHolder_grdResources_ctl02_...")The javascript isn't getting called when I add the call in code behind. I'm adding it like this in the OnLoad event:btnAdd.OnClientClick = "callback('" + sUpdateButtonID + "');";
JBoyd
What happens if you hard code the JavaScript as a test? If you use the ClientId of the control it will resolve its naming container for you.
rick schott
@JBoyd - instead of just using SUpdateButtonID use SUpdateButton.ClientID. This will be the ASP generated ID with all the prefixed stuff that is added to each control on a page.
Ahmad
A: 

You could use hidden fields on the calling page to store any values you need for your callback. The pop-up can use window.opener to store the values in these hidden fields.

You can expand your window.open function to update a javascript variable on the page with a reference to the caller:

<asp:button onclientclick="buttonClicked(this)" />

var lastButton;
function buttonClicked(button) {
lastButton = button;
window.open(x);
return false;
}

If you make the hidden fields asp controls then you'll have access to them on the postback of the update panel.

Edit:

Consider a modalpopup to eliminate issues around people clicking on the calling page while you're expecting them to use the popup.

Kim R
A: 

The simpler (and working) solution I chose was to implement this using the ModalPopupExtender within a user control in the gridview cell. The user control contains the read-only results grid and the ModalPopupExtender. The popup allows you to edit the contents of that grid within the cell of the parent grid. Upon clicking the Add button, the mini grid is updated asynchronously.

A few key items that finally got me to a working solution...

  • Wrap the contents of the panel referenced in the PopupControlId property in an update panel
  • Hide and show the modal popup in code behind
  • A simple and good example of a gridview using multiple ModalPopupExtenders
JBoyd
This link gives an example of how to populate the panel dynamically so it's not recreated for every row in the gridview: http://www.aspdotnetcodes.com/Ajax_ModalPopup_PostBack_GridView.aspx
JBoyd
A: 

These Both ways works for me

(1) Via referencing ChildPage from MasterPAge

    ContentPlaceHolder_content.FindControl("dvwOrder").Controls.Clear();
    ((UpdatePanel)this.ContentPlaceHolder_content.FindControl("upOrders")).Update();

This code is inside Master Page and on my button click I am using contentplaceholder to find the reference for control inside it. Here dvwOrder is my DataView and "upOrders" is my UpdatePanel.

(2) Via Delegates

Put this delegate and eventhandler on Master Page outside any method

    public delegate void RefreshButtonClickHandler(object

sender, EventArgs e); public event RefreshButtonClickHandler onRefreshButtonClick;

inside the class inyour button click event do this

        if(null == onRefreshButtonClick)
        {
            return;                
        }

        onRefreshButtonClick(sender, e);

Then In Child page's Page_Load Method tie this event with local handler

        Child child = (child) this.Master;
        reports.onRefreshButtonClick += new

Child .RefreshButtonClickHandler(reports_onRefreshButtonClick);

Here Child is my codebehind file's name

create

    void child_onRefreshButtonClick(object sender, EventArgs e)
    {

    }

and you are done

Ved
A: 

I abandoned my efforts to do this in a seperate window and developed the solution instead using an AJAX ModalPopupExtender. Matt Berseth's example was very helpful.

To update the child grid contained in an update panel within the parent grid, I stored the value of the row from which the button was clicked in a session variable and then using that value called the databind method of the child grid once the user had made their selections and clicked save.

protected void btnShowSkillsetPopup_Click(object sender, EventArgs e)
{
    // get the gridviewrow from the sender so we can get the datakey we need
    Button btnAddSkillsetsFromRow = sender as Button;
    GridViewRow row = (GridViewRow)btnAddSkillsetsFromRow.NamingContainer;

    Session["CapRes_ResourceRequestID"] = Convert.ToString(this.grdResources.DataKeys[row.RowIndex].Value);
    Session["CapRes_SkillsetUpdatePanel_Row"] = Convert.ToString(row.RowIndex);
    ModalPopupExtender.Show();
}

Save code...

int nUpdatePanelID = Convert.ToInt32(Session["CapRes_SkillsetUpdatePanel_Row"].ToString());
UpdatePanel pnlSkillsetsMain = grdResources.Rows[nUpdatePanelID].FindControl("pnlSkillsetsMain") as UpdatePanel;
GridView grdSkillsets = pnlSkillsetsMain.Controls[0].FindControl("CascadingSkillsets1").FindControl("grdSkillsets") as GridView;
grdSkillsets.DataBind();

ModalPopupExtender.Hide();
JBoyd
+1  A: 

You can use javascript function __doPostBack('eventTarget','eventArgument'). In Client side perhaps looks like this.

function showPopup()
{
 var return = window.showModalDialog('someurl','','');
 if(return)
 {
  // do postback for update
  __doPostBack('<%= hiddenButton.ClientID %>','eventArgument');
 }
}

in server side you should use Update Panel with UpdateMode=Conditional and hidden button like rick schott says. The tricky part is to know which cell that needs to update. If you wired OnClick for hiddenbutton then it will fired that event when _doPostBack called. You can access Request.Form["_EVENTARGUMENT"] from server side to access value that __doPostBack sent. You can play with this value for instance which cell that need to update.

yose r
+1 as this was the same idea I had and a good explanation. Also @JBoyd read this for further information http://aspalliance.com/895 on the __doPostBack javascript event. Using this method I believe that you can trigger the update now limited to the specific update panel. On the aspect when its closed, you may want to use a Close button as opposed to the window.close event and link the jscript accordingly.
Ahmad