Behind the Scenes – ModalPopupTemplate

The ModalPopupTemplate control is a Composite Control—or a control that is a collection of other controls and implements the CreateChildControls method.

This post demonstrates how the ModalPopupTemplate (MPT) was created and also points out a few of its current weaknesses and areas for improvement (hey, I’m honest…).

Attaching Custom Events

As with any control, the MPT has an array of external properties available. Most importantly are the three events and the styling properties.

To attach custom events to a control, they are implemented similar to a property; however, the method used to attach the event is a virtual method. Let’s take a look at our OkClick event. The other events follow suit in functionality.

// Events of Popup

publiceventEventHandler OkClick;

protectedvirtualvoid OnOkClick(EventArgs e)

{

if (OkClick != null)

{

OkClick(this, e);

}

}

Our OkClick accepts EventHandler events and can be used for UpdatePanel triggers, etc; however, our control needs action methods (On_) to link events to methods on your page. That’s where the virtual method comes in.

Later in the code, when the Ok, Close, and Cancel buttons are generated, there’s one more bit of code. The Click events are optional so we still need to tie a bit of functionality to them to close the popup window. This is done by mixing a bit of JavaScript into the mix.

if (OkClick != null)

{

// If an OK Behavior is assigned, use it.

okButton.Click += OkClick;

}

else

{

// If not, the OK button just hides the popup.

okButton.OnClientClick = “$find(‘popup’).hide(); return false;”;

}

Prefabricated Style Sheets and Custom Style Sheets

A template has to have a few styles built into it. This is currently an “under construction” area of the control as there has to be a way to generic it up a bit and lose the ugly case statements.

When the DefaultStyle property is set to Custom, this code is bypassed or simply there isn’t a “style” attached to the control. You’ll get plain black text, white background, and no borders. If DefaultStyle isn’t specified in the control, the YUI theme is applied.

if (DefaultStyle != PopupStyle.Custom)

{

string includeLocation = “”;

switch (DefaultStyle)

{

casePopupStyle.YUI:

includeLocation =

Page.ClientScript.GetWebResourceUrl(this.GetType(),

“ModalPopupTemplate.Resources.ModalPopupTemplateStyle_YUI.css”);

break;

casePopupStyle.Clean:

includeLocation =

Page.ClientScript.GetWebResourceUrl(this.GetType(),

“ModalPopupTemplate.Resources.ModalPopupTemplateStyle_Clean.css”);

break;

default:

break;

}

HtmlLink cssLink = newHtmlLink();

cssLink.Href = includeLocation;

cssLink.Attributes.Add(“rel”, “stylesheet”);

cssLink.Attributes.Add(“type”, “text/css”);

this.Page.Header.Controls.Add(cssLink);

}

This code retrieves the embedded resource URL from the library and adds a link to it in the page’s header.

Generating the ModalPopupExtender

The GenerateExtender method accepts one parameter: the control you wish to add the popup extender into. You could remove the parameter and simply add it to the composite control’s ControlCollection, but I wanted to keep it open for later development.

privatevoid GenerateExtender(Control container)

{

// Todo: Fix these hardcoded ID values for PopupControlId.

ModalPopupExtender mpe = newModalPopupExtender();

mpe.BehaviorID = popupBehaviorId;

mpe.BackgroundCssClass = ModalBackgroundStyle;

mpe.PopupControlID = “popupPanel”;

mpe.TargetControlID = TargetControlId;

container.Controls.Add(mpe);

}

The code sets every property that you’d normally set on a ModalPopupExtender. The only matter of disconnect at the moment is the PopupControlID’s value—I don’t like that hardcoded between this and the GeneratePanel method, but it’s minor for the time being.

Generating the Popup Panel

The popup panel’s code is cut down a bit for the post as it’s repetative: generate a Panel control, several labels for the header and body text, a few buttons and a link button, and then put it all together.

The most important part is to ensure that the DIV containers enclose the proper controls and that every tag closes itself, etc.

First off, we see the popupPanel setting it’s ID (to match the ID set in the ModalPopupExtender), CSS Class, and an additional style attribute to hide it (to prevent the blip of it appearing on page load).

The rest of the HTML and controls are interwoven between LiteralControls for exact HTML output.

popupPanel.ID = “popupPanel”;

popupPanel.CssClass = PanelStyle;

popupPanel.Style.Add(HtmlTextWriterStyle.Display, “none”);

popupPanel.Controls.Add(

newLiteralControl(“<div class='” +

ContainerStyle + “‘>\n\t<div class='” +

HeaderStyle + “‘>\n\t\t”));

popupPanel.Controls.Add(headerText);

popupPanel.Controls.Add(closeButton);

popupPanel.Controls.Add(

newLiteralControl(“\n\t</div>”));

popupPanel.Controls.Add(

newLiteralControl(“\n\t<div class='” +

BodyStyle + “‘>\n\t\t”));

popupPanel.Controls.Add(bodyText);

popupPanel.Controls.Add(

newLiteralControl(“\n\t</div>”));

popupPanel.Controls.Add(

newLiteralControl(“\n\t<div class='” +

FooterStyle + “‘>”));

popupPanel.Controls.Add(okButton);

popupPanel.Controls.Add(cancelButton);

popupPanel.Controls.Add(

newLiteralControl(“\n\t</div>\n</div>”));

Finally, this method, GeneratePanel, also accepts a control parameter to add the control to a specified collection.

Putting it together — CreateChildControls

The Composite Control’s method — CreateChildControls — is where the magic happens.

protectedoverridevoid CreateChildControls()

{

base.Controls.Clear();

if (!this.ChildControlsCreated)

{

GenerateExtender(this);

GeneratePanel(this);

}

base.CreateChildControls();

}

It’s usually a good practice to clear the composite control’s ControlCollection before starting—just to be sure that you know exactly what’s being rendered. From there, call our Extender and Panel generation methods and place them in Composite Control’s control collection (this).

That’s it, you’re ready to add it to the page. For more information about how to add it to the page and the control’s parameters, as well as the full source code and a demonstration site, visit the Creating a Modal Popup Template Control posting from 5 November 2007.

Like this:

Related

I have been playing with your control lately. It’s very nice work. I am trying to extend it a bit, but some of what is going on is honestly a bit over my head. My goal is to be able to set a “pre render” (in quotes because its not the best way to put it) that would allow me to cancel the showing of the modal dialog. For instance. If you have a toolbar with items, often the individual items don’t have click events, rather the toolbar itself does, and a commandText type parameter is available in the event args to determine which button was pressed. If you only wanted the modal dialog for one or two of those buttons, a “pre-render” type event would allow us to catch that commandText parameter, and call cancel on the Modal control.

Is this something that is possible? I have been looking through your source, and the part that I havn’t come to grips with, is exactly how the TargetControlId property sets off the CreateChildControls function.

Let me ponder this a bit. I’m right in the middle of packing up my computer (actually, this is the last email check for the next few days while it travels), but will try to get back to you ASAP with a few ideas and some explanation.🙂

Matthew Vines

July 21, 2008 at 3:01 pm

Hello again sir. I was wondering if you have had a chance to think about how to add a pre-condition delegate or call to this control. I have played with it a bit, but have been largely unsuccessful.