Search code examples
c#asp.netupdatepanelajaxcontroltoolkitmodalpopupextender

Refreshing UpdatePanel after click event of a Button inside a modalpopup inside a UserControl


I have a page with a listbox and a user control placed inside an update panel like this:

<%@ Register TagPrefix="uc1" TagName="CMessage" Src="~/Controls/CMessage.ascx" %>
<ajaxToolkit:ToolkitScriptManager runat="server" ID="ToolkitScriptManager1" EnableScriptGlobalization="true" EnableScriptLocalization="true" />
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:ListBox ID="lbox" runat="server"></asp:ListBox>
            <asp:Button ID="btnDelete" OnClick="btnDelete_Click" runat="server" Text="Delete selected item" Enabled="True"></asp:Button>
            <uc1:CMessage ID="CMessage1" runat="server" />
        </ContentTemplate>
    </asp:UpdatePanel>

The page codebehind is like this:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        lbox.Items.Add("test1");
        lbox.Items.Add("test2");
    }
}
protected void btnDelete_Click(object sender, EventArgs e)
{
    CMessage.MessageConfirm("Delete item?", "Yes", "No", DeleteItem);
}
protected void DeleteItem()
{
  lbox.Items.Remove(lbox.SelectedItem);
  CMessage.Message("Item deleted succesfully!");
}

The user control is like this:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CMessage.ascx.cs" Inherits="Controles.CMessage" %>
    <table id="tableMessage" runat="server" style="display: none" class="modalPopup">
        <tr>
            <td>
                <asp:Label ID="lb5" runat="server" Text="Message"></asp:Label>
            </td>
        </tr>
        <tr>
            <td>
                <asp:Label ID="lbMessage" runat="server"></asp:Label>
            </td>
        </tr>
        <tr>
            <td>
                <asp:Button ID="btnOk" runat="server" Text="Ok" OnClick="btnOk_Click" />
                <asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClick="btnCancel_Click" />
            </td>
        </tr>
   </table>
   <asp:Button ID="btnOKError" runat="server" Text="OK" style="display: none" />    
   <ajaxToolkit:ModalPopupExtender ID="ModalPopupMessage" runat="server" TargetControlID="btnOKError" PopupControlID="tableMessage" OkControlID="btnOKError" CancelControlID="btnOKError"></ajaxToolkit:ModalPopupExtender>

The usercontrol codebehind is like this:

public partial class CMensaje : UserControl
{
    public delegate void FunctionButtonPressed();

    private FunctionButtonPressed FunctionButtonPressedOk
    {
        get { return (FunctionButtonPressed)Session["FunctionButtonPressedOk"]; }
        set { Session["FunctionButtonPressedOk"]= value; }
    }
    protected void btnOk_Click(object sender, EventArgs e)
    {
        ModalPopupMenssage.Hide();
        if (FunctionButtonPressedOk!= null)
        {
            FunctionButtonPressedOk();
        }
    }
    protected void btnCancel_Click(object sender, EventArgs e)
    {
        ModalPopupMessage.Hide();
    }
    public void Mensaje(string message)
    {
        lbMessage.Text = message;
        FunctionButtonPressedOk= null;
        btnCancel.Visible = false;
        ModalPopupMessage.Show();
    }
    public void MessageConfirm(string message, FunctionButtonPressed FunButtonOkx)
    {
        lbMessage.Text = message;
        FunctionButtonPressedOk= FunBotonAceptarx;
        btnCancel.Visible = true;
        ModalPopupMensaje.Show();
    }
}

Everything works, the popup is shown, the function to call from the page is passed to the usercontrol to trigger it if the user presses ok and triggers correctly etc. But in that last function DeleteItem() the changes done to the page (in this example the item removed from the listbox and the notification message launched) doesnt work.

Its like the updatepanel doesnt refresh. I cant call manually UpdatePanel1.Update() because i have the updatemode as always. In theory in this part of the pagecycle it should refresh the pages with the changes...

I tried adding in the user control pageload the OK button as a PostBackTrigger of the UpdatePanel with no avail and as an AsyncPostBackTrigger.

Keep in mind that this is an slimmed down version of the page and the user control so people can focus on the problem at hand so if you need any more details ask me...

The code flow is like this:

  1. User clicks in the delete item button and triggers the btnDelete_Click() in the page (first postback)

  2. btnDelete_Click() calls the usercontrol CMessage.MessageConfirm passing DeleteItem as argument

  3. At the usercontrol MessageConfirm() shows the modalpopup and saves the argument function DeleteItem() in order to call it later(end of first postback)

  4. After displaying the modalpopup the user clicks its Ok button and triggers the btnOk_Click() in the usercontrol (second postback)

  5. At the usercontrol btnOk_Click() calls the DeleteItem() function that was saved previously

  6. At the page DeleteItem() removes the item from the ListBox (lets say i dont call the second message to simplify, this would be the end of the second postback, and the update panel hasnt refreshed :S)

I think i have isolated the problem, moved all the controls and functions from the usercontrol to the page, the problem persisted, but if i called the DeleteItem() function directly instead of his delegate it worked (keep in mind that in both cases the breakpoint at DeleteItem() triggered so the function code was executing correctly):

protected void btnOk_Click(object sender, EventArgs e)
    {
        ModalPopupMenssage.Hide();
        /*if (FunctionButtonPressedOk!= null)
        {
            FunctionButtonPressedOk();
        }*/
        DeleteItem(); //page updates correctly! why?
    }

Is there some incompatibility with delegates?


Solution

  • In the end i solved it changing the following lines:

    if (FunctionButtonPressedOk!= null)
            {
                //FunctionButtonPressedOk();
                Page.GetType().InvokeMember(FunctionButtonPressedOk.Method.Name, BindingFlags.InvokeMethod, null, Page, new []{sender, e});
            }
    

    Why it works this way?Whats the difference internally?