Geeks With Blogs
CodeSpeaker A .NET developers blog
More often than not i see redundant code for displaying popups with AJAX and encapsulated
markup in copy/paste html containers. This might seem like an easy and fast way to program
at first, but as soon as you need to change the popup location of those 50 dialogs,
or change the blue backgrounds to green on those 30 rounded-corner containers,
you (should) start thinking about how you can improve these tasks.

Templating allows us to reuse our controls and to avoid the mess that copy/paste code creates.
In this example, i will show you how to create a simple AJAX modal popup control where all
popup specific functions and looks are defined in a single user control which can act as the
base for all types of popups in your project.

We start by adding a new UserControl called DialogContainer to our website with the following markup:


<%@ Control Language="C#" AutoEventWireup="true" CodeFile="DialogContainer.ascx.cs" Inherits="DialogContainer" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>

<asp:Button ID="ButtonPopupTrigger" Style="display: none;" runat="server" />
<ajaxToolkit:ModalPopupExtender ID="PopupExtender"
runat
="server"
TargetControlID
="ButtonPopupTrigger"
PopupControlID
="PanelDialog" />

<asp:Panel ID="PanelDialog" runat="server" style="display: none;">
<table cellpadding="5" cellspacing="0">
<tr>
<td style="background-color: #ddd">
<asp:Literal ID="LiteralTitle" runat="server" />
</td>
<td style="background-color: #ddd" align="right">
<asp:LinkButton ID="LinkButtonClose" Text="X" runat="server" />
</td>
</tr>
<tr>
<td style="background-color: #eee" colspan="2">
<asp:PlaceHolder ID="PlaceHolderContentTemplate" runat="server" />
</td>
</tr>
</table>
</asp:Panel>



So far so good. Pay attention to the PlaceHolder in the markup.
This is where all custom markup will be generated at. The surrounding markup and AJAX code
will serve as the the common functionality and looks of all popups that uses this control.
The code behind looks as follows:


using System;
using System.Web.UI;

public partial class DialogContainer : System.Web.UI.UserControl
{
[TemplateContainer(
typeof(ContentContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateInstance(TemplateInstance.Single)]
public ITemplate ContentTemplate { get; set; }

public class ContentContainer : Control, INamingContainer {}

public String Title
{
set { LiteralTitle.Text = value; }
}

protected void Page_Init()
{
// If a content template has been defined on the parent page then initialize the content template
if (ContentTemplate != null)
{
// Instantiate and initialize the content container class
ContentContainer container = new ContentContainer();
ContentTemplate.InstantiateIn(container);

// Add the content template to the placeholder so that we can see the user content
PlaceHolderContentTemplate.Controls.Add(container);
}
}

public void Show()
{
PopupExtender.Show();
}
}



What we do here is to define a TemplateContainer called ContentTemplate which acts
as the placeholder for all custom markup in the same way that a Repeater lets you
define an ItemTemplate. Notice the minimalistic class ContentContainer which acts
as our naming container and exposes the properties of the UserControl to the
parent page. Note that we allow the user to set a Title as well as a method called
Show() to display the popup.

To show how the control works on a webform we add it to our default aspx page like this:


<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register src="DialogContainer.ascx" tagname="DialogContainer" tagprefix="uc" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Templated UserControls</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager id="ScriptManager1" runat="server" />
<div>
<asp:Button ID="ButtonOpenDialog" Text="Open the dialog" OnClick="ButtonOpenDialog_Clicked" runat="server" />

<uc:DialogContainer ID="Dialog1" Title="Dialog 1" runat="server">
<ContentTemplate>
Click
<asp:LinkButton ID="LinkButtonIceCream" Text="here" OnClick="LinkButtonIceCream_Clicked" runat="server" /> if you like ice cream
</ContentTemplate>
</uc:DialogContainer>

<uc:DialogContainer ID="Dialog2" Title="Dialog 2" runat="server">
<ContentTemplate>
Thank you
</ContentTemplate>
</uc:DialogContainer>
</div>
</form>
</body>
</html>


 
Notice the two DialogContainer instances in the markup.
They are both instances of our dialog control yet implement different markup
within their respective ContentTemplate´s. Also notice that the first dialog control
contains an asp:LinkButton with an event. This event doesnt belong to the UserControl itself
as you might think at first but instead belongs to the page which instantiates the control.
This allows us to handle any page/dialog specific code directly in the page.

If you prefer to have the controls and events of your templated controls put elsewhere then
one suggestion would be to create a new UserControl which uses the DialogControl internally
so that you can handle the controls and events there instead of on the page itself.
You might have a dialog for exporting data, another one for approving an action or another one
for plain error messages. These dialogs would then be custom yet use the DialogContainer as
its base for basic dialog functionality and looks whereas the ugly alternative would be
copy/pasting your AJAX popup and looks markup to each of these new dialog UserControls.

And lastly, the page code behind:


using System;

public partial class _Default : System.Web.UI.Page
{
protected void ButtonOpenDialog_Clicked(object sender, EventArgs e)
{
Dialog1.Show();
}

protected void LinkButtonIceCream_Clicked(object sender, EventArgs e)
{
Dialog2.Show();
}
}



As you can see, templating allows you to create more maintainable code with ease
and keep that DRY beast within you tamed and happy :)


Posted on Saturday, July 4, 2009 11:27 AM ASP.NET | Back to top


Comments on this post: Templated User Controls in ASP.NET for Better Maintainability

# re: Templated User Controls in ASP.NET for Better Maintainability
Requesting Gravatar...
Thank you so much for this article. Not many people are implementing ContentTemplates on their controls. What a help!
Left by Brad on Sep 18, 2009 8:19 PM

# re: Templated User Controls in ASP.NET for Better Maintainability
Requesting Gravatar...
Thanks. Im glad its been useful to you :)
Left by Johan on Sep 18, 2009 8:22 PM

# re: Templated User Controls in ASP.NET for Better Maintainability
Requesting Gravatar...
Thank you so much !!
Left by YuTao on Sep 21, 2009 3:59 AM

# re: Templated User Controls in ASP.NET for Better Maintainability
Requesting Gravatar...
After reading this i went to my manager and i was like "Yo dawg, i heard you like controls, so i put some templates in your controls so you can now have controls in your controls."
Thanks for pimping my controls dawg.
Left by Nahual on Nov 28, 2009 12:54 AM

# re: Templated User Controls in ASP.NET for Better Maintainability
Requesting Gravatar...
Hi ,very nice article.
How can I have the same behavior without <ContentTemplate> tags?
With that tags the controls inside the DialogContainer will be not visible directly, and I need to do a FindControl :( .

Thanks
Left by AColabuf on Jul 18, 2012 5:15 PM

Your comment:
 (will show your gravatar)
 


Copyright © CodeSpeaker | Powered by: GeeksWithBlogs.net | Join free