ASP.NET 控件开发之旅(一)

  很多朋友都在问.NET控件开发 到底有多难(看到很多博友发自己的一些控件,我在想自己开发的就有好几十个了,与其一个个发,不如直接讲给大家听如何开发的,同时在讲解的过程把一些控件发给大家呵呵),其实可以轻松的告诉大家有恒心就能成绩来着,最好的控件全部在你身边,想开发高效好用的空间那就必须参考微软本身优秀的控件.为此我们手头要有一个好的工具Reflector.exe,这个大名鼎鼎的Reflector 你还不知道的话,只能被笑话了(窃笑),好了 大家伙自己百度谷歌找下,然后继续我们的文章,对于控件的使用我初略的给.NET 控件使用开发人员分了一个等级:

1.       会使用ASP.NET 控件(简单的自定义控件,还有服务器控件),对事件=其他知识完全没有概念

2.       掌握了页面事件的初步框架,能在不同事件中处理控件逻辑

3.       开发控件,运用属性以及理解HtmlTextWriter 输出的基本特性

4.       开发复杂控件,整合CSS,JS 以及缓存,主题==各种功能的 综合性控件

看看你自己处于那个阶段,是不是还停留在只会用用GridView ==控件的一些初级阶段呢?其实想摆脱现状就必须从整个页面事件去了解,对于页面事件我会在接下来的文章好好给大家分析来着.

 通过本文希望大家从控件开发中,深入理解 .NET 页面事件,以及各种控件开发中的设计模式(其实透过.NET FRAMEWORK中的Controls类的设计就能明白微软的意图),以及委托在事件中的使用,和一些基本的正则使用.当然最后是控件的完美开发咯

废话不多说.先给大家分析一个 我们经常用到的控件ASP.NET Button 控件

我们打开Reflector找到 System.Web.UI.WebControls这个命名控件,然后找到Button控件,我们展开

 

3.bmp

 

4.bmp找到Button 控件, 然后继续展开Button,

我这里和大家讲讲分别是什么意思就好了  其他的大家自己去看了 不过不理解的 我们可以一起讨论,还可以为你解释一下,那些控件我基本通看了一下 嘿嘿

Base Types 是他的基本类型,Derived Types 是他的派生类,红色的那些图标是她的 方法,带有手的图标是 属性,闪电的图标是 事件 ,.ctor() 就是构造函数 cctor 就是静态构造函数,EventClick , EventCommand 是类成员 .好了 基本就这样了 大家有什么不明白的可以在这里提问,我也会及时回答的.其实 Button 控件包含的意义很深,看明白了 对以后的控件开发有很大的帮助

比如他的

Code

 

AddAttributesToRender这个方法 就很好的展示给大家 ASP.NET 只如何处理INPUT 各种属性的呢.

 

下面分享我开发工程中的一个控件

这个控件是支持Url 分页的

当然 原理 是利用IList 的索引 取不同的数据 对于偷懒和后台管理很方便,至于前台的分页我想你更喜欢用存储过程 ROW_NUMBER() IDENTITY 方案来分页吧

 

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Text;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Text.RegularExpressions;

using System.Collections;

 

namespace YSMV.XWShop1B2C.Control

{

    [DefaultProperty("Text")]

    [ToolboxData("<{0}:YsmvRepeater runat=\"server\" AllowPage=\"true\" PageSize=\"10\" ShowPage=\"true\"></{0}:YsmvRepeater>")]

    public class YsmvRepeater : Repeater

    {

      

        //Static param

        private static readonly Regex RX;

        private static readonly object EventPageChanged;

 

        static YsmvRepeater()

        {

            RX = new Regex(@"^&page=\d+", RegexOptions.Compiled);

            EventPageChanged = new object();

        }

 

        //Static constants

        protected const string HTML1 = "<table cellpadding=0 cellspacing=0 class='inputTable'><tr><td colspan=2>";

        protected const string HTML2 = "</td></tr><tr><td class=paging align=left>";

        protected const string HTML3 = "</td><td align=right class=paging>";

        protected const string HTML4 = "</td></tr></table>";

        private const string LINK_PREV = "<a href=?page={0}>&#060;&nbsp;Previous</a>";

        private const string LINK_MORE = "<a href=?page={0}>More&nbsp;&#062;</a>";

        private const string KEY_PAGE = "page";

        private const string COMMA = "?";

        private const string AMP = "&";

 

        protected string emptyText;

        private IList dataSource;

        private int pageSize = 10;

        private int currentPageIndex;

        private int itemCount;

        private bool allowPage = false;

        private bool showPage = true;

 

        [Browsable(true)

        , Category("Appearance"),

        DefaultValue(true),

        Description("是否显示翻页链接")

        ]

        public bool ShowPage

        {

            get { return showPage; }

            set { showPage = value; }

        }

        [Browsable(true),

        Category("Appearance"),

        DefaultValue(true),

        Description("是否允许分页")]

        public bool AllowPage

        {

            get { return allowPage; }

            set { allowPage = value; }

        }

        [Browsable(true),

        Category("Appearance"),

        DefaultValue(10),

        Description("每页显示的数量")

        ]

        public int PageSize

        {

            get { return pageSize; }

            set { pageSize = value; }

        }

        [Browsable(true),

        Category("Appearance"),

        DefaultValue(""),

        Description("无记录时候显示的内容")]

        public string EmptyText

        {

            set { emptyText = value; }

        }

        override public object DataSource

        {

            set

            {

                //This try catch block is to avoid issues with the VS.NET designer

                //The designer will try and bind a datasource which does not derive from ILIST

                try

                {

                    dataSource = (IList)value;

                    ItemCount = dataSource.Count;

                }

                catch

                {

                    dataSource = null;

                    ItemCount = 0;

                }

            }

        }

        protected int PageCount

        {

            get { return (ItemCount - 1) / pageSize; }

        }

 

        virtual public int ItemCount

        {

            get { return itemCount; }

            set

            {itemCount = value;}

        }

 

        virtual public int CurrentPageIndex

        {

            get { return currentPageIndex; }

            set { currentPageIndex = value; }

        }

 

        public void SetPage(int index)

        {

            //OnPageIndexChanged(new DataGridPageChangedEventArgs(null, index));

            OnPageIndexChanged(new GridViewPageEventArgs(index));

        }

 

        override protected void OnLoad(EventArgs e)

        {

            if (Visible)

            {

                string page = Context.Request[KEY_PAGE];

                int index = (page != null) ? int.Parse(page) : 0;

                SetPage(index);

            }

        }

 

        /// <summary>

        /// Overriden method to control how the page is rendered

        /// </summary>

        /// <param name="writer"></param>

        override protected void Render(HtmlTextWriter writer)

        {

 

            //Check there is some data attached

            string page = Context.Request[KEY_PAGE];

            int index = (page != null) ? int.Parse(page) : 0;

            if (ItemCount == 0)

            {

                writer.Write(emptyText);

                return;

            }

            //Mask the query

            string query = Context.Request.Url.Query.Replace(COMMA, AMP);

            query = RX.Replace(query, string.Empty);

 

            // Write out the first part of the control, the table header

            writer.Write(HTML1);

 

            // Call the inherited method

            base.Render(writer);

 

            // Write out a table row closure

            writer.Write(HTML2);

 

            //Determin whether next and previous buttons are required

            //Previous button?

            if (currentPageIndex > 0)

            {

                if (ShowPage)

                    writer.Write(string.Format(LINK_PREV, (currentPageIndex - 1) + query));

            }

 

            //Close the table data tag

            writer.Write(HTML3);

 

            //Next button?

            if (currentPageIndex < PageCount)

            {

                if (ShowPage)

                    writer.Write(string.Format(LINK_MORE, (currentPageIndex + 1) + query));

            }

 

            //Close the table

            writer.Write(HTML4);

        }

 

        override protected void OnDataBinding(EventArgs e)

        {

            if (!allowPage)

            {

                base.DataSource = dataSource;

                base.OnDataBinding(e);

                return;

            }

            //Work out which items we want to render to the page

            int start = CurrentPageIndex * pageSize;

            int size = Math.Min(pageSize, ItemCount - start);

 

            IList page = new ArrayList();

 

            //Add the relevant items from the datasource

            for (int i = 0; i < size; i++)

                page.Add(dataSource[start + i]);

 

            //set the base objects datasource

            base.DataSource = page;

            base.OnDataBinding(e);

 

        }

 

        //public event DataGridPageChangedEventHandler PageIndexChanged;

        public event GridViewPageEventHandler PageIndexChanged

        {

            add

            {

                Events.AddHandler(EventPageChanged, value);

            }

            remove

            {

                Events.RemoveHandler(EventPageChanged, value);

            }

        }

        virtual protected void OnPageIndexChanged(GridViewPageEventArgs e)

        {

            GridViewPageEventHandler pagehandler = (GridViewPageEventHandler)Events[EventPageChanged];

            if (pagehandler != null)

                pagehandler(this, e);

        }

    }

}

代码已经加了注释,细心的朋友 可能发现和 PETSHOP 中的控件很相似 ,,我是用那个修改的,我优化了他的事件private static readonly object EventPageChanged; 呵呵 ,好的 大家期待我的下个作品吧.

 

posted @ 2008-12-17 10:19  Sai~  阅读(2709)  评论(15编辑  收藏  举报