先说说几个教训:
1,小心命名,别跟系统已经存在的命名起冲突,比如,我一时疏忽将控件的命名空间设成Control,编译通过后,运行总是不通过,查了半天,才发现这个小问题,再比如,NAMEspace别和类名相同,否则,写起来很是不方便
下面是WEBTIMER的全部代码加了注解的
using System;
using System.Web.UI;
using System.Text;
using System.Web;
using System.Data;
using System.ComponentModel;

namespace MyControl


{

/**//// <summary>
/// WebTimer 的摘要说明。
/// </summary>
///Designer属性指定一个类作为设计时类,该类必须派生于ControlDesigner类,并且实现GetDesignHtml方法
///Designer性性是System.ComponentModel空间的类
///WebTimer继承了IPostBackEventHandler是因为任何要利用POSTBACK机制来进行事件处理的控件都必须
///继承该接口并实现RaisePostbackEvent方法
[Designer(typeof(MyControl.WebTimerDesigner))]
public class WebTimer:System.Web.UI.Control,System.Web.UI.IPostBackEventHandler

{

成员变量定义#region 成员变量定义
private int _interval=5000;//计时器种子数
private bool _enable=true;//是否允许此计时器
private static object TimerKey=new object();//TimerKey是做什么用的呢,它是用来做Events的KEY对象的,而且它是静态的,所以,对于类的所有实例,将只耗费一个变量的代价
#endregion


属性定义#region 属性定义
[Browsable(true),Bindable(true),DefaultValue(5000),Description("计时器使用的种子数")]
public int Interval

{

set
{_interval=value;}

get
{return(_interval);}
}

[Browsable(true),Bindable(true),DefaultValue(true),Description("是否允许计时器")]
public bool Enable

{

get
{return _enable;}

set
{_enable=true;}
}

[Browsable(true),Bindable(true),DefaultValue(true),Description("是否输出控件")]
public override bool Visible

{
get

{return base.Visible;}
set

{base.Visible = value;}
}

#endregion


事件定义#region 事件定义
public event EventHandler Timer

{

add
{Events.AddHandler(TimerKey,value);}

remove
{Events.RemoveHandler(TimerKey,value);}
}
#endregion


方法定义#region 方法定义

/**//// <summary>
/// 这个私有方法是用来在引发POSTBACK事件后,调用事件处理的关键,它再调用相应的事件处理程序
/// </summary>
private void ProcessTimer(string eventArgument)

{
EventHandler TimerHandler=(EventHandler)Events[TimerKey];
if(TimerHandler!=null)
TimerHandler(this,EventArgs.Empty);
}

private string BuildJavascript()

{
StringBuilder JsBuilder=new StringBuilder();

JsBuilder.AppendFormat("<script language='javascript'>setTimeout(\"
{0}\",{1});</script>",new object[]
{Page.GetPostBackEventReference(this),Interval});
return(JsBuilder.ToString());
}

#endregion


IPostBackEventHandler 成员#region IPostBackEventHandler 成员

/**//// <summary>
/// 每个要使用POSTBACK机制并且想在POSTBACK后进行适当处理的控件
/// 必须实现IPostBackEventHandler的RaisePostBackEvent方法
/// 并在此方法中调用或间接调用事件处理程序
/// </summary>
/// <param name="eventArgument"></param>
public void RaisePostBackEvent(string eventArgument)

{
// TODO: 添加 WebTimer.RaisePostBackEvent 实现
ProcessTimer("");
}
#endregion


OnRender方法用来输出HTML#region OnRender方法用来输出HTML
protected override void Render(HtmlTextWriter writer)

{
if(Page!=null)
Page.VerifyRenderingInServerForm(this);
if(_enable)
writer.Write(BuildJavascript());
}

#endregion


OnPreRender方法用来产生HTML#region OnPreRender方法用来产生HTML
protected override void OnPreRender(EventArgs e)

{
base.OnPreRender (e);
Page.GetPostBackEventReference(this,"");
//发现这一句可以不加,如果见了的话呢,DOPOSTBACK将会被绘制在前面,否则,绘制在后面
}
#endregion
}
}
相应的Designer
using System;
using System.Web.UI;
using System.Web.UI.Design;
using System.Text;
namespace MyControl


{

/**//// <summary>
/// WebTimerDesigner 的摘要说明。
/// </summary>
public class WebTimerDesigner:System.Web.UI.Design.ControlDesigner

{
public override string GetDesignTimeHtml()

{
StringBuilder HtmlBuilder=new StringBuilder();
Control TimerControl=(Control)this.Component;
if(TimerControl is MyControl.WebTimer)

{

HtmlBuilder.AppendFormat("<span id=\"
{0}\" style=\"border:1px solid #666666;font-size:9pt;font-weight:bold\" >{1}</span>",new object[]
{TimerControl.ClientID,"WebTimer"});
}
return(HtmlBuilder.ToString());
}
}
}
调用页面的HTML

<%
@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="TimerDemo.WebForm1" %>

<%
@ Register TagPrefix="cc1" Namespace="MyControl" Assembly="MyControl.WebTimer" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<cc1:WebTimer id="WebTimer1" runat="server"></cc1:WebTimer>
</form>
</body>
</HTML>
相应的代码
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace TimerDemo


{

/**//// <summary>
/// WebForm1 的摘要说明。
/// </summary>
public class WebForm1 : System.Web.UI.Page

{
protected MyControl.WebTimer WebTimer1;
private void Page_Load(object sender, System.EventArgs e)

{
// 在此处放置用户代码以初始化页面
}


Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)

{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/**//// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()

{
this.WebTimer1.Timer += new System.EventHandler(this.WebTimer1_Timer);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void WebTimer1_Timer(object sender, System.EventArgs e)

{
Response.Write(DateTime.Now);
}
}
}