我们先来实现grid类,代码如下:

grid.cs

using system;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.linq;
using system.text;
using system.threading.tasks;
using system.web.ui;

namespace aspnetservercontrol
{
    [designer("aspnetservercontrol.design.griddesigner, aspnetservercontrol.design")]//设计时支持,需要另外写一个对就的类
    [toolboxdata("")]
    [toolboxbitmap(typeof(grid), "toolbox.grid.bmp")]
    [description("表格控件")]
    [parsechildren(true)]
    [persistchildren(false)]
    [controlbuilder(typeof(notallowwhitespaceliteralsbuilder))]
    public class grid : controlbase
    {

        #region 属性

        #region datasource
        private object _datasource;
        public object datasource
        {
            get { return _datasource; }
            set { _datasource = value; }
        }
        #endregion

        #region columns
        private gridcolumncollection _columns;
        /// 
        /// 列数据
        /// 
        [category(categoryname.options)]
        [notifyparentproperty(true)]
        [persistencemode(persistencemode.innerproperty)]
        [editor(typeof(gridcolumnseditor), typeof(system.drawing.design.uitypeeditor))]//用于编辑器
        public virtual gridcolumncollection columns
        {
            get
            {
                if (_columns == null)
                {
                    _columns = new gridcolumncollection(this);

                }
                return _columns;
            }
        }
        #endregion

        #endregion


        protected override void render(htmltextwriter writer)
        {
            base.render(writer);
            if (_columns == null)
            {
                return;
            }
            writer.write("");
            renderheader(writer);
            renderbody(writer);
            writer.write("");
        }

        private void renderheader(htmltextwriter writer)
        {
            writer.write("");
            foreach (gridcolumn column in columns)
            {
                writer.write(string.format("{0}", column.headertext));
            }
            writer.write("");
        }

        private void renderbody(htmltextwriter writer)
        {
            datatable dt = datasource as datatable;
            if (dt == null || dt.rows.count ");
            foreach (datarow row in dt.rows)
            {
                writer.write("");
                foreach (gridcolumn column in columns)
                {
                    writer.write(string.format("{0}", row[column.datafield]));
                }
                writer.write("");
            }
            writer.write("");
        }
    }
}

1.grid类前面的几个属性相当重要:

(1).designer是设计时支持,需要另外写一个类库来支持。

(2).parsechildren指示页分析器应如何处理页上声明的服务器控件标记中嵌套的内容,也就是这个属性决定了grid内部还可以再嵌套其他内容(为true时才可嵌套),比如columns。

2.继承自controlbase,该类后面会介绍。

3.datasource属性是数据源。

4.columns是grid的内部列,其中[editor(typeof(gridcolumnseditor), typeof(system.drawing.design.uitypeeditor))]这个特性非常重要,该特性指示了该属性columns可以在编辑中编辑。其中gridcolumnseditor是界面编辑的类,后面会介绍。

5.重载render方法。该方法是将grid最终html形式输出。这里以table的形式来实现grid。

(1)将columns中的所有列的列名以table中的th呈现

(2)将数据源转换成datatable,然后遍历每一行,并将每一行的数据以td的形式呈现。

下面来看一下controlbase类。

controlbase.cs

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.web.ui;

namespace aspnetservercontrol
{
    public class controlbase : control, inamingcontainer
    {
    }
}

controlbase类继承自control类及inamingcontainer接口,这是自定义控件所必须的。

再来看一下notallowwhitespaceliteralsbuilder类

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using system.web.ui;

namespace aspnetservercontrol
{
    /// 
    /// 控件内部不允许存在非标签形式的字符串
    /// 
    internal class notallowwhitespaceliteralsbuilder : controlbuilder
    {
        /// 
        /// 不允许空白字符
        /// 
        /// 
        public override bool allowwhitespaceliterals()
        {
            return false;
        }

        /// 
        /// 忽略游离于标签外的字符串
        /// 
        /// 
        public override void appendliteralstring(string s)
        {
        }

        public override type getchildcontroltype(string tagname, system.collections.idictionary attribs)
        {
            return base.getchildcontroltype(tagname, attribs);
        }

    }
}

notallowwhitespaceliteralsbuilder主要是用来控制控件内部不允许存在非标签形式的字符串。

后面将会说明gridcolumnseditor及gridcolumn字段的定义,具体请看《asp.net服务器控件开发的grid实现(二)》