ModalPopupExtender doesn't work until AFTER a postback

Last post 11-01-2006 1:19 PM by DuctTapeMan2.0. 3 replies.

Sort Posts:

  • ModalPopupExtender doesn't work until AFTER a postback

    10-31-2006, 7:30 PM

    I'm trying to build a control that makes a consistent popup window appearance using the ModalPopupExtender.  It worked fine in the "Atlas" builds, but now with the renamed "Ajax" builds it no longer does.

    What now happens is when I click the trigger control, it posts back to the server and refreshes the entire page.  After it has posted back if I click the trigger control again, THEN the popup will appear.

    I'll post the code for my control and try to add some comments so you can tell what I'm up to:

    1    
    2    [ParseChildren(false)]
    3    [PersistChildren(true)]
    4    public class ModalWindow : IDMControl, INamingContainer
    5    {
    6    	private ModalPopupExtender extender;
    7    	private Panel panel;
    8    	private UpdatePanel body;
    9    	private ImageButton closeBox;
    10   	private Button hiddenShowButton;
    11   
    12   	private string targetControlID;
    13   	private string title;
    14   
    15   	public string TargetControlID
    16   	{
    17   		get { return targetControlID; }
    18   		set { targetControlID = value; }
    19   	}
    20   
    21   	public string Title
    22   	{
    23   		get { return title; }
    24   		set { title = value; }
    25   	}
    26   	
    27   	// Controls added to the HTML tag on the page actually get added to the internal UpdatePanel's controls.
    28   	public override ControlCollection Controls
    29   	{
    30   		get
    31   		{
    32   			EnsureChildControls();
    33   			return body.ContentTemplateContainer.Controls;
    34   		}
    35   	} 
    36   
    37   	// This is so I can easily get at the actual child controls collection 
    38   	// for the "wrap" controls like the close button, update panel, etc.
    39   	private ControlCollection MyControls
    40   	{
    41   		get { return base.Controls; }
    42   	}
    43   	
    44   	// This is another double-check to make sure that HTML-added controls
    45   	// are added to the update panel, not the direct child controls collection
    46   	protected override void AddParsedSubObject(object obj)
    47   	{
    48   		EnsureChildControls();
    49   		Control c = obj as Control;
    50   		if (c != null)
    51   		{
    52   			body.ContentTemplateContainer.Controls.Add(c);
    53   		}
    54   
    55   	}
    56   
    57   	protected override void CreateChildControls()
    58   	{
    59   		MyControls.Clear();
    60   
    61   		// This is the panel that gets displayed/hidden
    62   		panel = new Panel();
    63   		panel.ID = "PopupPanel";
    64   		panel.CssClass = "ModalWindow";
    65   		MyControls.Add(panel);
    66   
    67   		// This is the update panel so that postbacks can occur inside the dialog
    68   		// without posting back the entire page (which would get rid of the dialog)
    69   		body = new UpdatePanel();
    70   		body.ID = "body";
    71   		body.UpdateMode = UpdatePanelUpdateMode.Conditional;
    72   		body.RenderMode = UpdatePanelRenderMode.Block;
    73   		panel.Controls.Add(body);
    74   
    75   		// This is the X box in the upper-right
    76   		closeBox = new ImageButton();
    77   		closeBox.ID = "Close";
    78   		closeBox.AlternateText = "Close";
    79   		closeBox.ImageUrl = "/images/close.gif";
    80   		closeBox.ToolTip = "Close Window";
    81   		MyControls.Add(closeBox);
    82   
    83   		// Extender is supposed to display PopupPanel when <targetControlID>,
    84   		// in my case the ID of a LinkButton outside this control, is clicked.
    85   		extender = new ModalPopupExtender();
    86   		extender.ID = "MPE";
    87   		extender.PopupControlID = "PopupPanel";
    88   		extender.BackgroundCssClass = "ModalBackground";
    89   		extender.DropShadow = true;
    90   		extender.Enabled = true;
    91   		extender.TargetControlID = targetControlID;
    92   		extender.CancelControlID = "Close";
    93   		MyControls.Add(extender);
    94   	}
    95   
    96   	// The extender is rendered, then the show/hide panel.  Inside that panel, markup
    97   	// to make a header bar and border, plus the close box is rendered.  After that,
    98   	// the UpdatePanel (body) is rendered which contains whatever the contents of the
    99   	// <IDM:ModalWindow /> tag are.
    100  	protected override void Render(HtmlTextWriter w)
    101  	{
    102  		panel.Width = (this.Width == Unit.Empty) ? Unit.Pixel(500) : this.Width;
    103  		panel.Height = (this.Height == Unit.Empty) ? Unit.Pixel(400) : this.Height;
    104  
    105  		extender.RenderControl(w);
    106  		panel.RenderBeginTag(w);
    107  
    108  		// Header
    109  		w.AddAttribute(HtmlTextWriterAttribute.Class, "Header");
    110  		w.RenderBeginTag(HtmlTextWriterTag.Div);
    111  		w.AddAttribute(HtmlTextWriterAttribute.Class, "FloatRight");
    112  		w.RenderBeginTag(HtmlTextWriterTag.Span);
    113  		closeBox.RenderControl(w);
    114  		w.RenderEndTag();
    115  		w.Write(title ?? "Popup Window");
    116  		w.RenderEndTag();
    117  
    118  		// Body
    119  		w.AddAttribute(HtmlTextWriterAttribute.Class, "Body");
    120  		w.RenderBeginTag(HtmlTextWriterTag.Div);
    121  		body.RenderControl(w);
    122  		w.RenderEndTag();
    123  
    124  		panel.RenderEndTag(w);
    125  	}
    126  
    127  }
    

     
    And so the behavior is like this:

    1. Load Page
    2. Click the TargetControlID - Page refreshes and a bunch of WebResource.axd scripts that weren't previously on the page are rendered.
    3. Click the TargetControlID again, and the modal window appears.
    I'm fairly sure that the problem is related to the WebResource.axd scripts not rendering to the page on the first try - but I don't know how to correct it.
  • Re: ModalPopupExtender doesn't work until AFTER a postback

    10-31-2006, 9:44 PM
    • Contributor
      4,482 point Contributor
    • jodywbcb
    • Member since 03-12-2003, 3:52 PM
    • West Seattle,WA
    • Posts 985

    I think... if you call the createchildcontrols on the pre-init phase you may solve the problem...additionally - since you are doing this from code-behind...  I think you need to explicitly add the controls to the UpdatePanels's updatepanelcontrolcollections....in codebehind if we do not associate the controls with the update panel and actually associated it with the control collection... then the behavior you described would almost be expected (its a quirk of the scriptmanager which manages all that)....

     

    related thread 1 

     

     

    -- jody
    My Blogs on .Net 2.0 and Ajax
    http://csk.wbcb.com
    http://ArtbyJody.com
  • Re: ModalPopupExtender doesn't work until AFTER a postback

    11-01-2006, 10:02 AM
    jodywbcb:

    I think... if you call the createchildcontrols on the pre-init phase you may solve the problem...additionally - since you are doing this from code-behind...  I think you need to explicitly add the controls to the UpdatePanels's updatepanelcontrolcollections....in codebehind if we do not associate the controls with the update panel and actually associated it with the control collection... then the behavior you described would almost be expected (its a quirk of the scriptmanager which manages all that)....

    A control doesn't have a PreInit phase, only Init.  I tried overriding OnInit and calling CreateChildControls after the call to base.OnInit but that resulted in the following:

    [ArgumentNullException: Value cannot be null.
    Parameter name: page]
       Microsoft.Web.UI.ScriptManager.GetCurrent(Page page) +125
       AjaxControlToolkit.ExtenderControlBase.GetScriptReferences() +43
       Microsoft.Web.UI.ExtenderControl.Microsoft.Web.UI.IExtenderControl.GetScriptReferences() +7
       Microsoft.Web.UI.ScriptControlManager.RegisterScriptsForExtenderControls() +128
       Microsoft.Web.UI.ScriptManager.OnPreRender(EventArgs e) +402

    I don't really understand what you are saying about explicitly adding the controls to the updatepanel's updatepanelcontrolcollection. In my code, the overridden Controls getter is supposed to reroute the child controls of my ModalWindow to be the child controls of the update panel.

    The intent is to start with this markup:

      

    <asp:LinkButton runat="server" ID="MyLink" Text="Show Popup Window" />
    
         ... html ...
    
    <IDM:ModalWindow runat="server" ID="MyPopupWindow" TargetControlID="MyLink" Title="Popup Title">
         <IDM:Something runat="server" ID="MyPopupWindowContents" />
    </IDM:ModalWindow>

     And to have the resulting control tree:

    • MyLink
    • (other html)
    • ModalWindow
      • Modal extender
      • Panel that the modal extender shows/hides
        • CloseBox
        • UpdatePanel (so that postbacks can occur inside modal window)
          • The "Something" control
  • Re: ModalPopupExtender doesn't work until AFTER a postback

    11-01-2006, 1:19 PM
    Answer

    I found the answer - it was related to this Known Issue.

    My ModalWindow control was being used on the HTML layout of a skinned control, much like the skinned controls that CommunityServer (these forums) use.  During the skinned control's CreateChildControls method, the control loads an ASCX file and attaches to the controls inside it.  However, this was not happening until the PreRender phase, so the ScriptManager missed the ModalPopupExtender.  After a postback, the ModalWindow's controls were created during the Load State phase, which is much earlier.

    Adding EnsureChildControls to the OnLoad method of the base skinned control ensured that the ModalPopupExtender was created in time for the ScriptManager to see it and output the appropriate scripts the FIRST time around.
     

Page 1 of 1 (4 items)