咱们先来实现Grid类,代码以下:css
Grid.cshtml
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("<{0}:Grid Title=\"Grid\" runat=\"server\"><Columns></Columns></{0}:Grid>")] [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; /// <summary> /// 列数据 /// </summary> [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("<table border=\"1\" cellspacing=\"0\">"); RenderHeader(writer); RenderBody(writer); writer.Write("</table>"); } private void RenderHeader(HtmlTextWriter writer) { writer.Write("<tr>"); foreach (GridColumn column in Columns) { writer.Write(String.Format("<th >{0}</th>", column.HeaderText)); } writer.Write("</tr>"); } private void RenderBody(HtmlTextWriter writer) { DataTable dt = DataSource as DataTable; if (dt == null || dt.Rows.Count <= 0) { return; } writer.Write("<tbody>"); foreach (DataRow row in dt.Rows) { writer.Write("<tr >"); foreach (GridColumn column in Columns) { writer.Write(String.Format("<td >{0}</td>", row[column.DataField])); } writer.Write("</tr>"); } writer.Write("</tbody>"); } } }1.Grid类前面的几个属性至关重要:
(1).Designer是设计时支持,须要另外写一个类库来支持。服务器
(2).ParseChildren指示页分析器应如何处理页上声明的服务器控件标记中嵌套的内容,也就是这个属性决定了Grid内部还能够再嵌套其余内容(为true时才可嵌套),好比Columns。markdown
2.继承自ControlBase,该类后面会介绍。编辑器
3.DataSource属性是数据源。ide
4.Columns是Grid的内部列,其中[Editor(typeof(GridColumnsEditor), typeof(System.Drawing.Design.UITypeEditor))]这个特性很是重要,该特性指示了该属性Columns能够在编辑中编辑。其中GridColumnsEditor是界面编辑的类,后面会介绍。ui
5.重载Render方法。该方法是将Grid最终html形式输出。这里以table的形式来实现Grid。this
(1)将Columns中的全部列的列名以table中的th呈现spa
(2)将数据源转换成DataTable,而后遍历每一行,并将每一行的数据以td的形式呈现。.net
下面来看一下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 { /// <summary> /// 控件内部不容许存在非标签形式的字符串 /// </summary> internal class NotAllowWhitespaceLiteralsBuilder : ControlBuilder { /// <summary> /// 不容许空白字符 /// </summary> /// <returns></returns> public override bool AllowWhitespaceLiterals() { return false; } /// <summary> /// 忽略游离于标签外的字符串 /// </summary> /// <param name="s"></param> 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实现(二)》