C# 封裝控件 學習(2)

前篇文章簡單介紹瞭如何封裝Html來創建我們的ASP.NET服務器控件。這篇說說如何繼承ASP.NET獨有的WebControl類來製作標準服務器控件。

先來介紹下WebControl類

WebControl類:

WebControl 類從 Control 派生,用作定義 System.Web.UI.WebControls 命名空間中的所有控件的公共方法、屬性和事件的基類。提供所有 Web 服務器控件的公共屬性、方法和事件。通過設置在此類中定義的屬性,可以控制 Web 服務器控件的外觀和行爲。主要的屬性有:AccessKey、Attributes、 Width、Height等。此外,一個從 WebControl 派生的控件也自行參與到 ASP.NET 的主題功能。WebControl類的屬性和方法詳細的內容可以參看MSDN

這裏再簡單的說下WebControl和HtmlContrlol的區別:

Web控件和Html控件雖然好多功能相同並且長得很像,但是它們的內部實現機制是完全不一樣的。

Web控件具有回送功能,能夠用ViewState維持控件的狀態。Html控件則不能,當點擊頁面的操作,其狀態就會丟失。(ViewState後面會有講解)

Html控件與Web控件最大的區別是它們對事件處理的方法不同。對於Html窗體控件,當引發一個事件時,瀏覽器會處理它。但對於Web控件,事件僅由瀏覽器生成,但瀏覽器不會處理它,客戶端要給服務器發個信息,告訴服務器處理事件。 不過有些事件,
比如:按下鍵/移動/鼠標等事件,Asp.net中沒有這些事件(因爲這些事件即時性強,服務器處理得不夠及時),這時候Html控件就發揮其作用了,結合Html事件協助完成。

有的資料上說:Web控件要比Html控件執行效率要好。這個沒有太好的依據,僅供大家參考,高手也可以談談自己的想法。

自己動手:

這裏我們不像上篇文章那樣,簡單的創建一個類庫工程,而是直接創建ASP.NET服務器控件項目。

VS2008會自動的爲我們生成如下代碼:

namespace SelfServerControl
{
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>")]
    public class MyControl : WebControl
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? "[" + this.ID + "]" : s);
            }

            set
            {
                ViewState["Text"] = value;
            }
        }

        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write(Text);
        }
    }
}

代碼說明:

是不是有點熟悉,很像上節課繼承自Control類生成ASP.NET服務器控件的代碼。

代碼中定義了一個 Text 屬性(屬性的聲明和上篇基本一樣),並使用視圖狀態(ViewState )存儲該屬性值。使用視圖狀態保存回髮間的 Text 值。每次回發時,將重新創建頁並從視圖狀態還原值。如果 Text 值並未存儲在視圖狀態中,則在每次回發時會將值設置爲其默認的 Empty。ViewState 屬性繼承自 WebControl,是保存數據值的字典。通過使用 String 鍵,可輸入和檢索值。代碼中將“Text”用作鍵。字典中的項被類型化爲 Object,然後必須將其強制轉換爲屬性類型。

ViewState想必大家都已經很熟悉了,簡單的理解:當aspx頁面重新加載後,爲了避免上一次的存放在變量中的數據丟失,用ViewState來保存。

RenderContents 方法:

通常,在從 WebControl 派生控件並呈現單個元素時,應重寫 RenderContents 方法(而不是 Render 方法),以呈現控件標記中的內容。在呈現控件及其樣式屬性的開始標記之後,WebControl 的 Render 方法將調用 RenderContents。如果重寫 Render 方法以寫入內容,則控件將丟失生成到 WebControl 的 Render 方法中的樣式呈現邏輯。

如果我們將上篇的代碼複製到這裏,也能得到同樣的效果。這裏就不做演示了。

WebControl類爲開發人員提供了幾個特殊的方法,來完成我們對標註服務器控件的開發:

AddAttributesToRender(HtmlTextWriter.writer):WebControl的子類應該重寫該方法,以便包含用於呈現最外層HTML元素的HTML屬性的代碼塊
RenderBeginTag(HtmlTextWriter writer):WebControl的子類應該重寫該方法,以便包含用於呈現最外層HTML元素的打開標記的代碼塊
RenderContents(HtmlTextWriter writer): WebControl的子類應該重寫該方法,以便包含用於呈現最外層HTML元素的打開和關閉標記之間嵌套的HTML的代碼塊。
RenderEndTag(HtmlTextWriter writer):WebControl的子類應該重寫該方法,以便包含用於呈現最外層HTML元素的關閉標記的代碼塊

實現WebControl類的Render方法:

protected internal override void Render(HtmlTextWriter writer)

{

  RenderBeginTag(writer);

  RenderContents(writer);

  RenderEndTag(writer);

}

AddAttributesToRender方法中發生了什麼。該方法將在RenderBeginTag方法中被調用。

具體的實例在這裏就不做了,給大家一個參看的例子。

簡單應用:

ASP.NET給我們提供了很多現成的控件,比如Label,button,textbox等等。在平時的開發中,我們完全可以不繼承Webcontrol類,直接繼承它下面控件的子類,這樣更有助於我們項目中的應用和開發。下面說個以前在項目中用到的小實例。

namespace MyTextBox
{
    [DefaultProperty("Text"), ToolboxData("<{0}:BrianTextBox runat=server></{0}:BrianTextBox>"), Designer("System.Web.UI.Design.WebControls.PreviewControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    public class BrianTextBox : System.Web.UI.WebControls.TextBox
    {
        /// <summary>
        /// 構造函數
        /// </summary>
        public BrianTextBox()
            : base()
        {
            base.Attributes.Add("onfocus", "this.className='" + onFocus + "';");
            base.Attributes.Add("onblur", "this.className='" + onBlurCss + "';");
            base.CssClass = Class;
        }

        private string _onFocusCss = "colorfocus";
        [Bindable(true), Category("Appearance"), Description("文本框獲取焦點時觸發")]
        /// <summary>
        /// 獲取焦點時樣式
        /// </summary>
        public string onFocus
        {
            get { return _onFocusCss; }
            set { _onFocusCss = value; }
        }

        private string _onBlurCss = "colorblur";
        [Bindable(true), Category("Appearance"), Description("文本框失去焦點時觸發")]
        /// <summary>
        /// 失去焦點時樣式
        /// </summary>
        public string onBlurCss
        {
            get { return _onBlurCss; }
            set { _onBlurCss = value; }
        }

        private string _Class = "colorblur";
        [Bindable(true), Category("Appearance"), DefaultValue("")]
        /// <summary>
        /// 樣式
        /// </summary>
        public string Class
        {
            get { return _Class; }
            set { _Class = value; }
        }

        /// <summary>
        /// 獲取焦點的控件ID(如提交按鈕等)
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue("")]
        public string SetFocusButtonID
        {
            get
            {
                object o = ViewState[this.ClientID + "_SetFocusButtonID"];
                return (o == null) ? "" : o.ToString();
            }
            set
            {
                ViewState[this.ClientID + "_SetFocusButtonID"] = value;
                if (value != "")
                {
                    this.Attributes.Add("onkeydown", "if(event.keyCode==13){document.getElementById('" + value + "').focus();}");
                }
            }
        }
    }
}

代碼不是很難,簡單說下。這裏我不是繼承自WebControl類,而是繼承自它的子類TextBox類,向父類中添加了兩個屬性,分別代表失去焦點時的樣式和獲取焦點時的樣式。還有一個屬性是獲取焦點的控件ID。這裏默認的設定了css的類名稱,所以在使用時,需要創建兩個css:


<style>
    .colorblur
    {
        cursor:hand;
        background-color:Aquamarine;
        }
        
        
        .colorfocus
    {
        cursor:hand;
        background-color:Red;
        }
    </style>

不用做其他的任何設置,運行,會看到當我們得Textbox獲得焦點的時候背景色紅色,失去焦點時,背景是藍色。,當然,這裏只是做個例子,獲得和失去焦點的樣式大家可以自己去設計。

這只是簡單的小應用,給大家提個思路。大家完全可以開動自己創新思維,創造出自己獨特的服務器控件。靈活的運用在我們得項目開發中。

轉載地址:http://www.pin5i.com/showtopic-24404.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章