![]() |
Web Development »
User Controls »
General
Intermediate
Customizing user control layoutBy Mohammed Mahmoud TahtamouniAn article on customizing user controls, through special templates. Basically, it is a simple technique to wrap user controls. |
C#, Windows, .NET1.1, ASP.NET, WebForms, VS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

Designing Web pages is something, and designing nice looking pages and controls is something else, which is always one of the important factors in evaluating web application usability and look and feel. Usually, Web developers do not pay much attention on making nice looking pages and controls, also maintaining the look and feel for the entire application is a real headache we all know about. Besides, nowadays, we are getting non-stop demands on customizing layouts and personalizing pages, along with themes, coloring, and layout. With this article, I will try to introduce a simple technique to easily define and customize controls through templates designed through the IDE.
Customizing user controls is nothing but wrapping a control, with rich layout, borders, titles, and footers.

To make this technique work for your application, you need to have a base control for your web controls, where you can control the control's rendering behaviour. Nothing specific with this control except to have a property to hold the template ID, and override the Render method to apply the template through the template's services.
public class BaseUserControl: UserControl, IBaseUserControl
{
#region Private fields
private string _templateId = "";
private string _title = "";
#endregion Private fields
#region Public properties
public string TemplateId
{
get
{
return _templateId;
}
set
{
_templateId = value;
}
}
public string Title
{
get
{
return _title;
}
set
{
_title = value;
}
}
#endregion Public properties
protected override void Render(HtmlTextWriter writer)
{
//Apply template only when _templateId is not null.
if( _templateId != null)
{
CustomizedControlsTemplates.Global.
UserControlTemplate.ApplyTemplate(this,
writer, _templateId);
}
else
{
base.Render (writer);
}
}
//The basic render method, to be called from
//the template services, without causing cyclic calls
public void RenderUserControl(HtmlTextWriter writer)
{
base.Render (writer);
}
}
public interface IBaseUserControl
{
void RenderUserControl(HtmlTextWriter writer);
}
In the BaseUserControl class, the Render method will check the _templateId and call the ApplyTemplate, where the method RenderUserControl represents the primitive Render method.
Well, as you might have noticed, the BaseUserControl implements the interface IBaseUserControl, which enforces the user controls to implement the method RenderUserControl.
Templates are nothing but normal user controls, with a place holder, which could be replaced at run time with any user control, so the template is something like:
<script runat="server">
protected string hitTime = DateTime.Now.ToString("hh:mm:ss");
//overriding the method
public override void Control_Loaded()
{
base.MainPlaceHolder = MainPlaceHolder;
hitTime = DateTime.Now.ToString("hh:mm:ss");
}
</script>
<TABLE style="BORDER-COLLAPSE: collapse" cellSpacing="0"
cellPadding="0" border="0" ID="Table1">
...
...
<TR>
<TD width="2" background= "images/left.gif" height="100%"></TD>
<TD width="145" height="16">
<asp:PlaceHolder id="MainPlaceHolder" runat= "server">
</asp:PlaceHolder>
</TD>
<TD width="4" background="images/right.gif" height="100%"></TD>
</TR>
...
...
</TABLE>
The customized templates should inherit a base template MyTemplate that implements the interface IMyTemplate. Mainly, the MyTemplate class will implement the method SetPlaceHolderControl which overrides the Render method of the place holder. The new Render method will not render the place holder, instead, it will render the user control, by calling the method RenderUserControl, to avoid cyclic calls between Render and ApplyTemplate.
public class MyTemplate: UserControl,IMyTemplate
{
//the place holder to represent the user control
//location in the template.
public System.Web.UI.WebControls.PlaceHolder
MainPlaceHolder = new PlaceHolder();
//the LoadedBaseControl will be accessible
//from the templates.
public BaseUserControl LoadedBaseControl;
public MyTemplate()
{
}
protected override void Render(HtmlTextWriter writer)
{
//nothing specific here.
base.Render (writer);
}
private void BaseControlRenderMethod(HtmlTextWriter
output, Control container)
{
//just render the user control.
LoadedBaseControl.RenderUserControl(output);
}
//the following virtual method, allow
//flixible access to the controls.
virtual public void Control_Loaded()
{
}
virtual public void SetPlaceHolderControl(BaseUserControl
userControl, HtmlTextWriter writer)
{
LoadedBaseControl = userControl;
//call back to the template, to allow
//developers to have flixible access
//to the rendered control.
Control_Loaded();
//specify the rendering method to the place holder.
MainPlaceHolder.SetRenderMethodDelegate( new
RenderMethod(BaseControlRenderMethod));
//and now, render the place holder.
this.Render(new HtmlTextWriter(writer));
}
}
The method Control_Loaded could be overridden by the templates to do some logic before starting to render the control.
The templates defined in the web application can be loaded at application startup time. These templates could be placed in a hash table for later reference, as in the following code snippet:
public class Global : System.Web.HttpApplication
{
//the folloing is just a pointer
//to the UserControlTemplate service.
public static IUserControlTemplate UserControlTemplate =
new CustomizedUserControlTemplate();
//define the default template id for the applicarion.
public static string DefaultTemplateId = "SampleTemplate1";
//the following string array holds all defined templates id.
public static string [] AvailableTemplatesId =
new string[] {"SampleTemplate1","SampleTemplate2"};
//the folowing hash table used to hold the templates objects.
public static Hashtable AvailableTemplates =
new Hashtable(AvailableTemplatesId.Length);
...
protected void Application_Start(Object sender, EventArgs e)
{
//load all templates in the AvailableTemplates.
foreach(string templateId in AvailableTemplatesId)
{
if( AvailableTemplates.Contains(templateId) == false)
{
System.Web.UI.UserControl buc =
new System.Web.UI.UserControl();
AvailableTemplates.Add(templateId,
buc.LoadControl("~/" + templateId + ".ascx"));
}
}
}
...
}
In the Global class, I kept all template IDs in a string array AvailableTemplatesId, and the AvailableTemplates Hashtable will hold the loaded templates.
The class CustomizedUserControlTemplate will work like a service provider to apply the requested template according to the specified template ID. Besides, it could be used to set the default template for all controls. The method ApplyTemplate will verify the existence of the template, and load it from the cache and then apply the template through SetPlaceHolderControl.
The web controls may tell what the template ID to be used is, by setting the property TemplateId, or by setting this property to blank to apply the default template.
I provided an example to show two different templates, the page "TestControlsTemplates.aspx" contains one simple user control, check out this page to see how to switch between templates.
| You must Sign In to use this message board. | |||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 23 Feb 2006 Editor: Smitha Vijayan |
Copyright 2006 by Mohammed Mahmoud Tahtamouni Everything else Copyright © CodeProject, 1999-2010 Web19 | Advertise on the Code Project |