Asp.Net伺服器控制項開發的Grid實現(二),asp.netgrid
我們先來實現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("<{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。
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{ /// <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實現(二)》
ASPNET中我做了個GRIDVIEW控制項,控制項的第一個列是個CHECKBOX,第二列是個LABEL控制項
你是要這效果吧?看圖:
我的思路是這樣:你第一列做成模板列,裡面放一個checkbox,然後還要裝一個hidden控制項,其value也綁定uname欄位,當複選checkbox,查到其後面的hidden存的人名,然後遍曆所有的hidden,看哪個hidden的value與此相符,那麼選中其前面checkbox。
代碼(js部分我用了jquery):
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$("table#GridView1 input:checkbox").click(function () {
var uname = $(this).siblings("input:hidden").val();
var checked = $(this).attr("checked");
$("table#GridView1 input:hidden").each(function () {
if ($(this).val() == uname)
$(this).siblings("input:checkbox").attr("checked", checked);
});
});
});
</script>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="UID" DataSourceID="SqlDataSource1" EmptyDataText="沒有可顯示的資料記錄。">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server" />
<asp:HiddenField ID="HiddenField1" runat="server"
Value='<%# Eval("UName") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UName" SortExpression="UName">
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='&l......餘下全文>>
ASPNet中伺服器控制項的生命週期
(1)初始化:在此階段中,主要完成兩項工作:一、初始化在傳入Web請求生命週期內所需的設定;二、跟蹤檢視狀態。首先,頁面架構通過預設引發Init事件,並調用OnInit()方法,控制項開發人員可以重寫該方法為控制項提供初始化邏輯。此後,頁面架構將調用TrackViewState方法來跟蹤檢視狀態。需要注意的是:多數情況下,Control基類提供的TrackViewState方法實現已經足夠了。只有在控制項定義了複雜屬性時,開發人員才可能需要重寫TrackViewState方法。
(2)載入檢視狀態:此階段的主要任務是檢查ASP.NET伺服器控制項是否存在以及是否需要將其狀態恢複到它在處理之前的請求結束的狀態。因此該過程發生在頁面回傳過程中,而不是初始化請求過程。在此階段,頁面架構將自動回復ViewState字典。如果伺服器控制項不維持其狀態,或者它有能力通過預設儲存其所有狀態而使用ViewState字典,那麼開發人員則不必實現任何邏輯。針對那些無法在 ViewState字典中儲存的資料類型或者需要自訂狀態管理的情況,開發人員可以通過重寫LoadViewState方法來自訂狀態的恢複和管理。
(3)處理回傳資料:若要使控制項能夠檢查用戶端發回的表單資料,那麼必須實現System.Web.UI.IPostBackDataHandler介面的 LoadPostData()方法。因此只有處理回傳資料的控制項參與此階段。
(4)載入:至此階段開始,控制項樹中的ASP.NET伺服器控制項已建立並初始化、狀態已還原並且表單控制項反映了用戶端的資料。此時,開發人員可以通過重寫OnLoad()方法來實現每個請求共同的邏輯。
(5)發送回傳更改通知:在此階段,ASP.NET伺服器控制項通過引發事件作為一種訊號,表明由於回傳而發生的控制項狀態變化(因此該階段僅用於回傳過程)。為了建立這種訊號,開發人員必須再次使用System.Web.UI.IPostBackDataHandler介面,並實現另一方法- RaisePostBackChangedEvent()。其判斷過程為:如果控制項狀態因回傳而更改,則LoadPostData()返回true;否則返回false。頁面架構跟蹤所有返回true的控制項並在這些控制項上調用RaisePostDataChangedEvent()。
(6)處理回傳事件:該階段處理引起回傳的用戶端事件。為了便於將用戶端事件映射到伺服器端事件上進行處理,開發人員在此階段可以通過實現 System.Web.UI.IPostBackEventHandler介面的RaisePostBackEvent()方法來實現該邏輯。由此途徑,伺服器控制項將成功捕獲回傳的用戶端事件進行伺服器端的相應處理。
(7)預呈現:該階段完成在產生控制項之前所需要的任何工作。通常情況下是通過重寫OnPreRender()方法完成該工作。需要注意的是:在該階段,可以儲存在預呈現階段對控制項狀態所做的更改,而在呈現階段進行的更改則會丟失。
(8)儲存狀態:如果ASP.NET伺服器控制項不維持狀態,或者它有能力通過預設儲存其所有狀態而使用ViewState字典,那麼開發人員不必在該階段實現任何邏輯。因為這個儲存狀態的過程是自動的。如果ASP.NET伺服器控制項需要自訂狀態儲存,或者控制項無法在ViewState字典中儲存特殊的資料類型,則需要通過重寫SaveViewState()方法來實現狀態儲存。
(9)呈現:表示向HTTP輸出資料流中寫入標記文本的過程。開發人員通過重寫Render()方法使......餘下全文>>