咱們先來實現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實現(二)》