Introduction
This small server control is not my idea, I was browsing the net looking for nothing in particular until I stumbled across a site that sold server controls for ASP.NET. One of those controls was a WebTimer
control, I looked at it for 3 seconds and thought, why not make one my self, so I did.
I'm not going to explain in detail how the code works but for advanced and intermediate developers it should be pretty straight forward.
Down to the code
Ok, let's start, open a new "web control library" project in VS.NET. Give a suitable name, lets say WebTimerProject, after the project opens delete the file that VS generates and create a new one (so you can name it properly). Add new item - Web Custom Control, name it... WebTimer. The first lines of code after the namespace are:
[DefaultProperty("Text"),
ToolboxData("<{0}:WebCustomControl1 runat="server"></{0}:WebCustomControl1>")]
public class WebCustomControl1 : System.Web.UI.WebControls.WebControl
The default property is defined here; we will change it to the ID
property.
[DefaultProperty("ID"),
ToolboxData("<{0}:WebTimer runat="server"></{0}:WebTimer>")]
[DefaultEvent("IntervalExpired")]
public class WebTimer : System.Web.UI.WebControls.WebControl,
IPostBackDataHandler
As you can see we did the change to the default property and there are some other changes as well. First the DefaultEvent
, that way the control will know which event is the default and when we double click it in the design time it will open up the code behind, just the way we like it to do. We didn't declare the event yet but we will soon. The second thing we see here is the fact we inherit the IPostBackDataHandler
interface, that's because we want to be able to post back the client side script and fire an event when that happens on the server side.
public event EventHandler IntervalExpired;
This is the line where we declare the event, I called it IntervalExpired
.
private int interval=5000;
<Bindable(true)>
[Category("Data")]
[DefaultValue(5000)]
[Description("the interval set for the postback in millisec")]
public int Interval
{
get
{
return interval;
}
set
{
interval = value;
}
}
This is the property declaration, plain and simple, Interval
.
The next section is the Helper
function, but since I don't use it, I won't go into it too much. At first I thought I'll need the form name that the control is in, but then I found out I don't, anyway the function just stayed there and if you are going to develop a control yourselves this function is almost essential. It loops through the controls in the page and finds out the one that is holding the control.
The real juice is in the last part, control events. Here we have the events that are fired and the stuff that happens when they do.
protected override void Render(HtmlTextWriter output)
{
output.Write(this.ID);
}
This is the Render
override, I really don't use it much as you can see, I just put in the control ID
so you can see it in the design view. And this control has no visible GUI anyway on the client side. If you look back at the code:
public WebTimer()
{
this.Visible=false;
}
This is the constructor that makes the control invisible at runtime. (if anyone knows a better way to do this, please tell me).
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (Page != null)
{
Page.RegisterRequiresPostBack(this);
if(!Page.IsStartupScriptRegistered(this.ID+"_TCDooM"))
{
StringBuilder sb = new StringBuilder();
string sFormName = GetFormName(this.Page);
sb.Append("<script language="'javascript'">\n");
sb.Append("{\n");
sb.Append("window.setTimeout(\""+
Page.GetPostBackClientEvent(this,"")+
"\","+interval+");\n");
sb.Append("}\n");
sb.Append("</script>\n");
Page.RegisterStartupScript(this.ID+"_TCDooM",
sb.ToString());
}
}
}
This code is really all the control, on the init
event we add the code that will render the client side script. First we run the OnInit
event we inherit, then we check to see if the page is valid - if (Page != null
), then we register this control as a control that requires post back, this will in fact generate the code needed for post back at the client side (if you view the source of the HTML generated you'll see a function in the script named __postback
, that's it!). After that, we check to see if we already have that script block registered so we won't have it twice or more. Then the string builder is there to help us out building our string, nothing fancy, just a script
tag and the SetTimeout
function. The last line is the one that registers the script to the page so it will be rendered; the first parameter is the name we give it, the same name we checked to see if it already exists.
bool IPostBackDataHandler.LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
if(postDataKey==this.ID)
{
return true;
}
else
{
return false;
}
}
void IPostBackDataHandler.RaisePostDataChangedEvent()
{
IntervalExpired(this, EventArgs.Empty);
Those two methods are the implementation of the IPostBackDataHandler
interface. The first one is called whenever a post back is made for this control and if it returns true
the other one is fired. So when ever a postback is made with the id of the control we fire up the RaisePostDataChangedEvent
method and there we fire up the IntervalExpired
event. This event is the one you'll write code for in the code behind.
Conclusion
This is a small and easy to make control and I think that everyone who has a bit of development background can understand it. Just read the code and see what it does, some of the code is just copy-paste off the Internet. Just so you'll know, I wrote this in 3-4 hours; since I never wrote a server control before, so can you, I never knew how to register a client side code and how to make an event the default event and so on... So what I'm saying is - it's easy.