Introduction

Since Microsoft released the .NET Framework, a lot of component vendors have surfaced and some of them provide amazing controls at a very cheap price. However sometimes a customer asks you for something too specific that you can't buy anywhere so you have to do it yourself.

This is the case for this article. A customer wanted to offer the possibility to do online tests on his portal. However he wanted to be able to know the remaining time exactly while doing the tests as well as be able to change the appearance without recompiling. Of course when the time expires he wanted the test to finish immediately. So it was time to make a custom control with DHTML support...

Background

In order to fully understand the code, you should be familiar with the design time framework, OO JavaScript and DHTML.

As I don't have time to change the source code you will see that it's in Spanish. I'm sorry if you don't understand it. It's a nice and very used language so you should start learning it

Using the code

Using the timer in your code is very easy:

Add the Cronometro control to the toolbox.

Add a Cronometro control to a WebForm.

Set the control's properties (in order to work properly you should set the script and the images folder using ScriptPath and ImagesPath properties).

Add the following HTTP handler to your web.config if you want the control to show the images in design time:

The control uses a JavaScript file and has some predefined styles included so be sure to include them too in your deployments.

There's no limit to the number of timers you can use in a page. The control has been tested in IE 6.0, FireFox 1.0 and Opera 8.0.

Points of Interest

When you have to make a custom control that has logic on the server and the client side, it's important to think about how to pass values from the server side to the client side and vice versa.

In the server side I have all the properties but I needed to make them available to the client side because the timer is updated on the client side and the expiration check is also done there. IMHO the best way for doing this is to create a JavaScript class with the necessary fields and methods to have the job done. The control registers crono.js (where all the JavaScript code is) using RegisterClientScriptBlock in the prerender stage. Also, for each timer it creates an object with the following fields:

causePostBack: if it's true, the control will cause postback when the timer expires, generating the TimeOut event.

imgPath: path to the folder with the images for the styles.

timeSpan: instant of time when the timer expires.

serverInitTime: when exactly the timer starts (if it's not set, it will be set the first time in the prerender stage).

clientInitTime: client browser's time when the object is created.

serverInitLoadTime: instant of time when the page is in prerender stage for this roundtrip.

Instead of passing the InitialTime property directly I stored it in a hidden input field to allow to use the control to post a form's data to another page and be able to get the initial server time.

The client side methods are:

Tick: called every second to update the timer.

ShowRow: method to show/hide the row that shows a message when the timer expires.

DisplayTime: called from Tick to update the timer's digits.

GetInitialServerTime: helper method to get when exactly the timer starts (in server time).

GetTimeSpan: helper method to convert a string holding a TimeSpan value to a Date in JavaScript.

Only the Tick() method is a bit complex because it has the main timer logic.

The client side doesn't need to pass any value to the server side, as the server can find out if the timer has expired. However, the client side has to generate a server side event if the CausaPostBack property is set to true. In order to accomplish that, the control registers a function that will be called from Tick() when the timer expires, that uses Page.GetPostBackEventReference() to generate a postback.

The custom control has six images as children (one for each digit to show the timer in the format hh:mm:ss), that are created and added in CreateChildControls. The control implements INamingContainer to give unique names to its child controls as well as IPostBackEventHandler in order to be able to generate server side events.

The control has custom rendering to draw a table with two rows. On the first row it shows the digits, and the second row is used to display a message when the timer expires.

The control has a custom UITypeEditor to select the style as you can see in the picture at the top of this article.

To improve design time experience, I wanted the control to display images reflecting the selected style, but using ASP.NET 1.1 forces you to implement a custom handler to obtain the images from the assembly (in ASP.NET 2.0, this is improved, thanks to the WebResourceAttribute). The custom handler is implemented in the class DesignTimeImageHandler. The form used to select the control's style has some PictureBox controls and the framework automatically stores the associated bitmap as an image resource. Instead of adding the images as different embedded resources, I reused the images from the UITypeEditor.

The JavaScript needed by the control should be copied to a folder and the path should be set using the ImagesPath property. You can use a custom handler as done with the images in design time to obtain the JavaScript without having to set the path but I preferred this option because you can change the code easily without needing to recompile.

History

2005/10/13 - Initial version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

I used DHTML timer control within an update panel inside a gridview.I takes the end time from the database and bind the Initial Time property of the control from the database. It works for the first time.But not working with the gridview bind method.If I remove update panel it works fine but with postbak occurs.How can I use this control as other .net controls ? please help me...

This control does what I wanted.
I am trying to add the pause functionality.
I am using Cronometro with other AJAX controls, when they cause a post back I could pause the timer with a javascript variable. But I am not sure how to unpause it when the AJAX controls return.

hy
i've used ur control
it's great but o face a problem.
when i select an element from radiolist control, and press a button
it always give me selectedindex=0
and scondly the images used for displying time are making the process slow, is there anyway to use normal digits to display time???
please reply at qamarshahbaz2004@yahoo.com
qamar