Problem using ajax ModalPopupExtender with UpdatePanel

G

Greg

I have a ModalPopupExtender with an UpdatePanel on it. On the UpdatePanel is
a DropDownList, a MultiView, and OK and Cancel buttons. The View that's
shown on the MultiView depends on what item is selected on the DropDownList.
I have postback triggers for the OK and Cancel buttons.

When I show the ModalPopupExtender and click Cancel, the code behind the
Cancel button executes, the popup hides, and everything is fine. But if I
make a selection from the DropDownList and show one of the MultiView's Views
and then click Cancel, I get an error "Microsoft JScript runtime error:
Sys.InvalidOperationException: Handler was not added through the
Sys.UI.DomEvent.addHandler method." after the Cancel button's code executes.

While I prefer to have the OK and Cancel buttons on the UpdatePanel (there
are situations where I want to disable OK), I can live with them off the
UpdatePanel, but I couldn't get the popup to work with them off the
UpdatePanel either.

If anyone has gotten the ModalPopupExtender to work with an UpdatePanel, I'd
really appreciate hearing how, as I've spent over 2 days already trying to
get this to work. I can post the html I have if that would be useful.

Thanks!
Greg
 
G

Greg

I have some more information to add. I have another ModalPopupExtender with
an UpdatePanel on it, but the OK and Cancel buttons are NOT on the
UpdatePanel. This one throws the same error when I click OK/Cancel, but
again, only if I first click something on the UpdatePanel which does a
postback.

Also, this worked before, but appears to have broken after we upgraded from
VS2005/.Net 2.0 to VS2008/.Net 3.5.

Any help getting a ModalPopupExtender and UpdatePanel to work together would
be greatly appreciated!

Greg
 
O

Oli

Hi Greg, the good news is its fixable....but first, the reason it doesn't
work!!
Consider this piece of code..
..ASPX :
<asp:Button runat="server" ID="btnShowPopup" Text="Show Popup"/>
<asp:panel runat="server" ID="pnlPopup" SkinID="PopupPanel">
<asp:UpdatePanel runat="server" id="updPopup" ChildrenAsTriggers="true"
UpdateMode="Conditional">
<ContentTemplate>
<asp:Label runat="server" ID="lblPopupTest" Text="No Post Back Yet!" />
<asp:Button runat="server" ID="btnUpdate" OnClick="btnUpdate_Click"
Text="Update" />
<asp:Button runat="server" ID="btnCancel" Text="Close" />
</ContentTemplate>
</asp:UpdatePanel>
</asp:panel>
<ajaxtk:ModalPopupExtender runat="server" ID="mpePopup"
TargetControlID="btnShowPopup"
PopupControlID="pnlPopup" CancelControlID="btnCancel" />

..ASPX.CS (CodeBehind):

protected void btnUpdate_Click(object sender, EventArgs e)
{
this.lblPopupTest.Text = DateTime.Now.ToShortDateString();
}

Once the Update button is clicked the page will post back to the server via
the MS AJAX framework. When a response is received, the UpdatePanel (DIV) and
its' contents are removed from the DOM and rebuilt with the new data, and the
new DIV is added to the DOM. This replaces the original "btnCancel" control
which was registered by the modal popup, with a new "btnCancel" which has NOT
been registered. Although the new button (probably) has the same ID as the
button removed, it is not *exactly* the same control that the ModalPopup
originally registered as the CancelControl. That button no longer exists in
the DOM, but IS still referenced in the Javascript. Therefore when the
following code is run by the ModalPopupBehaviour.js when it calls its Dispose
method (when you navigate away from the page, for example) it calls the
following code...

if (this._cancelHandler && $get(this._CancelControlID)) {
$removeHandler($get(this._CancelControlID), 'click', this._cancelHandler);
this._cancelHandler = null;
}

"this._cancelHandler" holds the Event Handler method.
"this._CancelControlID" holds the original ID of the Cancel button BUT
"$get(this._CancelControlID)" will get the element in the DOM with the given
ID. IE the NEW button that has no events registered with the Modal Popup.

Therefore the above code matches the wrong button to the right handler, and
the error is thrown. You will also notice from this code that although no
error is thrown until Dispose is called, your popup will not disappear when
the Cancel button is clicked AFTER a postback. This is for the same reason.

Now...the solution!! Well actually there are two solutions, both related!

In the example given, the solution is to put the buttons outside the
updatepanel...

<asp:UpdatePanel runat="server" id="updPopup" ChildrenAsTriggers="true"
UpdateMode="Conditional">
<ContentTemplate>
<asp:Label runat="server" ID="lblPopupTest" Text="No Post Back Yet!" />
</ContentTemplate>
</asp:UpdatePanel>
<!-- Buttons Not In UpdatePanel and so not recreated -->
<asp:Button runat="server" ID="btnUpdate" OnClick="btnUpdate_Click"
Text="Update" />
<asp:Button runat="server" ID="btnCancel" Text="Close" />

This will work fine. However, if you cannot do this (if say the Cancel
button is part of a usercontrol), then you can wrap the lot in an updatepanel
and give it a trigger or call update from the code behind...

..ASPX :
<asp:UpdatePanel runat="server" id="updModalPopup" ChildrenAsTriggers="false"
UpdateMode="Conditional">
<ContentTemplate>
<asp:Button runat="server" ID="btnShowPopup" Text="Show Popup"/>
<asp:panel runat="server" ID="pnlPopup" SkinID="PopupPanel">
<asp:UpdatePanel runat="server" id="updPopup" ChildrenAsTriggers="true"
UpdateMode="Conditional">
<ContentTemplate>
<asp:Label runat="server" ID="lblPopupTest" Text="No Post Back Yet!" />
<asp:Button runat="server" ID="btnUpdate" OnClick="btnUpdate_Click"
Text="Update" />
<asp:Button runat="server" ID="btnCancel" Text="Close" />
</ContentTemplate>
</asp:UpdatePanel>
</asp:panel>
<ajaxtk:ModalPopupExtender runat="server" ID="mpePopup"
TargetControlID="btnShowPopup"
PopupControlID="pnlPopup" CancelControlID="btnCancel" />
</ContentTemplate>
</asp:UpdatePanel>

..ASPX.CS (CodeBehind):

protected void btnUpdate_Click(object sender, EventArgs e)
{
this.lblPopupTest.Text = DateTime.Now.ToShortDateString();
this.updModalPopup.Update();
}

And this will re-register the Controls correctly....

Hth,
Oli
 
G

Greg

Oli,

Thank you so much for your response, I'd just about given up and abandoned
the ModalPopupExtender.

If I'm reading this right, the full html for the first solution should look
like this?

<asp:Button runat="server" ID="btnShowPopup" Text="Show Popup"/>
<asp:panel runat="server" ID="pnlPopup" CssClass="modalPopup">
<asp:UpdatePanel runat="server" id="updPopup" ChildrenAsTriggers="true"
UpdateMode="Conditional">
<ContentTemplate>
<asp:Label runat="server" ID="lblPopupTest" Text="No Post Back
Yet!" />
</ContentTemplate>
</asp:UpdatePanel>
<!-- Buttons Not In UpdatePanel and so not recreated -->
<asp:Button runat="server" ID="btnUpdate" OnClick="btnUpdate_Click"
Text="Update" />
<asp:Button runat="server" ID="btnCancel" Text="Close" />
</asp:panel>
<ajaxToolkit:ModalPopupExtender runat="server" ID="mpePopup"
TargetControlID="btnShowPopup"
PopupControlID="pnlPopup" CancelControlID="btnCancel" />

With codebehind (for better or for worse, we use vb here):
Protected Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs)
Me.lblPopupTest.Text = DateTime.Now.ToShortDateString()
End Sub

Clicking the Update button here caused the popup to disappear. Probably
because btnUpdate is outside the update panel? The fix for this seemed to be
an async trigger on btnUpdate, and this actually seemed to work until I
navigated away from the page and THEN I got the same error! So I tried
adding mpePopup.Show() to the btnUpdate's Click event. THIS seems to work!
It does have a side effect of posting back to the page, so the whole page
flickers, but if this turns out to be the only issue, I can live with that.

I will try your second solution, however, to see if that works better. If I
did something wrong above, please let me know.

Thank you!
Greg
 
O

Oli

Hi Greg,
yes, you are right! I forgot to add the trigger. the page should look like
this..

<asp:Button runat="server" ID="btnShowPopup" Text="Show Popup" />
<asp:panel runat="server" ID="pnlPopup" CssClass="modalPopup">
<asp:UpdatePanel runat="server" ID="updPopup"
ChildrenAsTriggers="true" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label runat="server" ID="lblPopupTest" Text="No
Post Back
Yet!" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnUpdate"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<!-- Buttons Not In UpdatePanel and so not recreated -->
<asp:Button runat="server" ID="btnUpdate"
OnClick="btnUpdate_Click" Text="Update" />
<asp:Button runat="server" ID="btnCancel" Text="Close" />
</asp:panel>
<ajaxtk:ModalPopupExtender runat="server" ID="mpePopup"
TargetControlID="btnShowPopup"
PopupControlID="pnlPopup" CancelControlID="btnCancel" />

and that works fine in a test site. PM me on oferns at gmail dot com and I
can send you a simple zipped solution with a demo with both solutions in. I
have just tried the above method and it works fine so I would suggest that
perhaps you have another popup on the page? Anyways, PM me and I will send
you the file...

Cheers.
Oli
 
G

Greg

I've been delinquent in coming back to this, but I need to put this on the
record that both of Oli's solutions seem to be working for me. (And the
explanation in the Sept 2 post is excellent!) Thank you, thank you, thank
you!!

A few notes I should add:

1. As has already been noted, the original solution #1 was missing an
AsyncPostbackTrigger. The version in Oli's second post works great though.

2. With the second solution, where the whole lot is wrapped in an
UpdatePanel, the popup disappeared after the postback. The fix is to just
show the popup again after the postback, with this line at the end of
btnUpdate_Click:
this.mpePopup.Show();

3. The reason I was still getting an error when leaving the page was because
I did, in fact, have another modal popup on the page that I hadn't corrected
yet. When I commented out the extra modal popup, I no longer got the error.
So all modal popups on the page need to look like one of the 2 solutions
previously posted to avoid the error when leaving the page.

Hopefully this will save someone else some headaches...

Greg
 
R

rob8w8

Hi Greg

Try to keep the ModalPopupExtender off like

Enabled="false" and just before show change for Enabled="true".

For me it works.

Regards

rob8w8
 
R

Rahul

Hi Greg,

I tried to implement Login Control but I am getting error saying "Microsoft
JScript runtime error: Sys.InvalidOperationException: Two components with the
same id 'loginControl1_UpdateProgressLogin' can't be added to the
application." when clicking the cancel button which is under
ModalPopupExtender. I want to display Panel1(Test.aspx) at first time when
login is over .. it will go and PanelSignUp will be displayed. But on
clicking of any button I am gettting this errror. Please help me because from
the last 3 week I am working on this error.
Added some code .. Please have a look...
Test.aspx--------
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:panel ID="Panel1" runat="server">
<asp:LinkButton ID="lbSignIn" runat="server"
OnClick="ShowLoginMessage" EnableViewState="False">Sign In</asp:LinkButton>
<uc1:LoginControl ID="loginControl1"
OnLoginStatus="PopupLoginCntl_Completed" Visible="false"
runat="server" />
</asp:panel>

<asp:panel ID="PanelSignUp" runat="server" Visible="false">
<asp:Label ID="labelMgs" runat="server"
ForeColor="#CC0000"></asp:Label>
<asp:LinkButton ID="lbLogOut" runat="server"
EnableViewState="False">[Log Out]</asp:LinkButton>
</asp:panel>
</ContentTemplate>
</asp:UpdatePanel>

Test.aspx.cs--------------

protected void ShowLoginMessage(object sender, EventArgs e)
{
loginControl1.Visible = true;
loginControl1.EnableModelDialog(true);
}
protected void PopupLoginCntl_Completed(object sender, EventArgs e)
{
this.UpdatePanel1.Update();
loginControl1.EnableModelDialog(false);
if (loginControl1.IsLogin)
{
//loginStatus = true;
//PanelSignUp.Visible = true;
//labelMgs.Text = "Welcome " + loginControl1.Name + " ";
}
else
{
//PanelSignUp.Visible = false;
}
}

User Control --- LoginControl.aspx ----

<ajaxToolkit:ModalPopupExtender BackgroundCssClass="modalBackground"
DropShadow="true"
runat="server" PopupControlID="loginPanel" ID="loginModalPopupExtender"
TargetControlID="lbSignIn"/>

<asp:panel ID="loginPanel" runat="server" CssClass="modalPopup"
Height="254px" Width="405px"
OnLoad="loginPanel_Load">
<asp:UpdateProgress ID="UpdateProgressLogin"
AssociatedUpdatePanelID="loginUpdatePanel"
runat="server">
<ProgressTemplate>
<DIV id="IMGDIV" align="center" valign="middle" runat="server"
style="position:
absolute;visibility:visible;vertical-align:middle;border-color:black;">
<asp:panel ID="PanelUpdateProgress" runat="server"
Height="254px" Width="405px">
<table style="width: 405px; height: 254px;">
<tr>
<td align="right" valign="middle" style="width: 45%;">
<img src="Images/wait30.gif" />
</td>
<td align="left" valign="middle">
Loading...
</td>
</tr>
</table>
</asp:panel>
</DIV>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="loginUpdatePanel" runat="server"
UpdateMode="Conditional">
<ContentTemplate>

<asp:panel ID="PanelSignIn" runat="server" Height="254px"
Width="405px" DefaultButton="btnLogin">
<asp:Button ID="btnLogin" runat="server" BackColor="#FFFBFF"
BorderColor="#CCCCCC"
BorderStyle="Solid"
BorderWidth="1px" CommandName="Login" Font-Names="Verdana"
Font-Size="0.8em"
ForeColor="#284775" Text="Log In" OnClick="btnLogin_Click" />
<asp:Button ID="btnCancelLogin" runat="server" BackColor="#FFFBFF"
BorderColor="#CCCCCC"
BorderStyle="Solid"
BorderWidth="1px" CommandName="Login" Font-Names="Verdana"
Font-Size="0.8em"
ForeColor="#284775" Text="Cancel" OnClick="btnCancelLogin_Click" />
</asp:panel>
<asp:panel ID="PanelSignUp" runat="server" Height="254px"
Width="405px" Visible="false">
</asp:panel>
</ContentTemplate>
</asp:UpdatePanel>

</asp:panel>


LoginControl.aspx.cs ---------
protected void btnLogin_Click(object sender, EventArgs e)
{
loginModalPopupExtender.Show();
if (txtEmailLogin.Text == "")
{
txtEmailLogin.BorderColor = System.Drawing.Color.Red;
}
if (txtPasswordLogin.Text == "")
{
txtPasswordLogin.BorderColor = System.Drawing.Color.Red;
}
if (LoginStatus != null)
{
if (txtEmailLogin.Text.Equals("(e-mail address removed)") &&
txtPasswordLogin.Text.Equals("admin"))
{
status = true;
name = txtEmailLogin.Text;
LoginStatus(this, EventArgs.Empty);

loginModalPopupExtender.Hide();
}
else
{
//labMsg.Text = "<font color=red>Sorry user name and
password could not find</font>";
}
}
}

protected void btnCancelLogin_Click(object sender, EventArgs e)
{
PanelSignIn.Visible = true;
PanelSignUp.Visible = false;
LoginStatus(this, EventArgs.Empty);
loginModalPopupExtender.Hide();
}

public void EnableModelDialog(bool visibility)
{
if (visibility)
{
loginModalPopupExtender.Show();
//loginModalPopupExtender.CancelControlID = btnCancelLogin.ID;
}
else
{
loginModalPopupExtender.Hide();
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,815
Latest member
treekmostly22

Latest Threads

Top