ExtAspNet应用技巧(二十) - 如何创建ext:Timer控件


引子

在刚刚发布的 ExtAspNet v2.1.1版本中,应网友 要求添加了ext:Timer控件,实现的效果就是定时回发(AJAX)到服务器执行一段C#代码。
因为这个控件非常简单,没有页面可视元素,所以我就单独拿出来讲解一下,或许对大家阅读ExtAspNet源代码有一定的帮助。


使用Timer控件

先来看下使用Timer的例子( 在线版本):

ExtAspNet应用技巧(二十) - 如何创建ext:Timer控件

ASPX标签声明:

    <ext:PageManager ID="PageManager1" runat="server" />

    <ext:Timer ID="Timer1" Interval="3" Enabled="false" OnTick="Timer1_Tick" runat="server">

    </ext:Timer>

    <ext:Button ID="btnStartTimer" runat="server" Text="Start Timer" OnClick="btnStartTimer_Click">

    </ext:Button>

    <ext:Button ID="btnStopTimer" runat="server" Text="Stop Timer" OnClick="btnStopTimer_Click">

    </ext:Button>

    <br />

    <ext:Label ID="labServerTime" runat="server" Text="This is current datetime.">

    </ext:Label>

    


这里定义Timer1每隔3秒回发服务器一次(Interval="3"),默认不启用(Enabled="false"),同时定义后台事件处理函数(OnTick="Timer1_Tick")。


C#代码:
    protected void Timer1_Tick(object sender, EventArgs e)

    {

        labServerTime.Text = DateTime.Now.ToString();

    }

    protected void btnStartTimer_Click(object sender, EventArgs e)

    {

        Timer1.Enabled = true;

    }

    protected void btnStopTimer_Click(object sender, EventArgs e)

    {

        Timer1.Enabled = false;

    }

    


在每隔3秒的事件处理函数Timer1_Tick中,只是简单的将页面中Label控件的文本改变为当前服务器时间。


ExtAspNet中Timer的实现

    [ToolboxData("<{0}:Timer Interval=\"30\" runat=\"server\"></{0}:Timer>")]

    [ToolboxBitmap(typeof(Timer), "res.toolbox_icons.Timer.bmp")]

    [Description("定时器")]

    [DefaultEvent("Tick")]

    public class Timer : ControlBase, IPostBackEventHandler

    {

        #region properties



        /// <summary>

        /// 是否可用

        /// </summary>

        [Category(CategoryName.OPTIONS)]

        [DefaultValue(true)]

        [Description("是否可用")]

        public virtual bool Enabled

        {

            get

            {

                object obj = ViewState["Enabled"];

                return obj == null ? true : (bool)obj;

            }

            set

            {

                ViewState["Enabled"] = value;

            }

        }



        /// <summary>

        /// 定时间隔(单位:秒)

        /// </summary>

        [Category(CategoryName.OPTIONS)]

        [DefaultValue(30)]

        [Description("定时间隔(单位:秒)")]

        public int Interval

        {

            get

            {

                object obj = ViewState["Interval"];

                return obj == null ? 30 : (int)obj;

            }

            set

            {

                ViewState["Interval"] = value;

            }

        }



        #endregion

        #region OnPreLoad

        protected override void OnPreLoad(object sender, EventArgs e)

        {

            base.OnPreLoad(sender, e);

            SaveAjaxProperty("Enabled", Enabled);

        }

        #endregion

        #region OnPreRender

        protected override void OnPreRender(EventArgs e)

        {

            base.OnPreRender(e);

            // 不渲染

            RenderWrapperDiv = false;

            string setupScript = String.Format("box.{0}=window.setInterval(function(){{{1}}}, {2});", ClientJavascriptID, GetPostBackEventReference(), Interval * 1000);

            if (Enabled)

            {

                AddPageFirstLoadAbsoluteScript(setupScript);

            }



            if (AjaxPropertyChanged("Enabled", Enabled))

            {

                string ajaxScript = String.Format("window.clearInterval(box.{0});", ClientJavascriptID);

                if (Enabled)

                {

                    ajaxScript += setupScript;

                }

                AddAjaxPropertyChangedScript(ajaxScript);

            }

        }

        #endregion



        #region IPostBackEventHandler

        public void RaisePostBackEvent(string eventArgument)

        {

            OnTick(EventArgs.Empty);

        }

        #endregion

        #region OnTick

        private static readonly object _handlerKey = new object();

        /// <summary>

        /// 定时事件

        /// </summary>

        [Category(CategoryName.ACTION)]

        [Description("定时事件")]

        public event EventHandler Tick

        {

            add

            {

                Events.AddHandler(_handlerKey, value);

            }

            remove

            {

                Events.RemoveHandler(_handlerKey, value);

            }

        }



        protected virtual void OnTick(EventArgs e)

        {

            EventHandler handler = Events[_handlerKey] as EventHandler;

            if (handler != null)

            {

                handler(this, e);

            }

        }

        #endregion

    }

    


从上往下看,首先是声明两个属性Enabled和Interval,中间OnPreRender是用来向页面中输出JavaScript代码,后面是OnTick事件的定义。

下面主要讲解OnPreRender中的代码:

1. 不考虑AJAX的支持的支持

如果不考虑ExtAspNet中所谓的原声的AJAX支持,我们可以简单的把OnPreRender重写为:
    protected override void OnPreRender(EventArgs e)

    {

        base.OnPreRender(e);

        // 不渲染

        RenderWrapperDiv = false;

        string setupScript = String.Format("box.{0}=window.setInterval(function(){{{1}}}, {2});", ClientJavascriptID, GetPostBackEventReference(), Interval * 1000);

        if (Enabled)

        {

            AddPageFirstLoadAbsoluteScript(setupScript);

        }

    }

    

其中RenderWrapperDiv = false,用来说明此控件不需要向页面中输出任何HTML代码。
如果将上例中Enabled属性改为true,则会在页面中生成如下代码:
    box.__0=window.setInterval(function(){__doPostBack('Timer1','');}, 3000);

    

如图:
ExtAspNet应用技巧(二十) - 如何创建ext:Timer控件


2. 添加AJAX的支持

如果需要AJAX支持,那么我就需知道在此次的PostBack中,控件的那些属性发生了变化,ExtAspNet提供一套机制来完成这一任务,那就是你所看到的SaveAjaxProperty和AjaxPropertyChanged,我们有 一篇文章专门说明这一问题。

我们来看下在上例中,点击“Start Timer”和“Stop Timer”分别发生了什么:
Start Timer:

ExtAspNet应用技巧(二十) - 如何创建ext:Timer控件


Stop Timer:
ExtAspNet应用技巧(二十) - 如何创建ext:Timer控件


对比Timer的源代码,是不是很清晰,其实ExtAspNet的控件编写并不是很复杂,如果你有好的想法不妨自己先尝试一下。



下载全部源代码





你可能感兴趣的:(timer)