Asp.net自定義控件系列(一)

     最近看到公司某個網站中用到了自定義控件,咋一眼看去,不明白什麼玩意,web

網上一搜,好像確實不是幾句話就能寫出強大的自定義控件。好吧,做爲一個碼農,我決定從基本學起,寫一個關於自定義控件學習過程系列。windows

固然了,我只是學習這個系列,不是做爲一個master來出書寫教程了。瀏覽器

若是你以爲本身是個master,歡迎指出問題,一針見血的指出問題每每事半功倍。服務器

若是你以爲本身是個大菜鳥,歡迎學習交流。ide

這個系列主要學習web服務器自定義控件。學習

而web 服務器控件又分爲幾種:網站

HTML服務器控件、<input type=’text’ id=’id1’ runat=’server’>ui

ASP.NET標準服務器控件  <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>this

自定義服務器控件:這就是我想學習,想寫的重點了。spa

 

我以爲吧,學習任何東西,都應該先從微軟官方去學習,大概瞭解了知識後再去網上看其餘的博客文章什麼的,由於每一個人的理解不同,或者人家理解了,可是寫出來的沒有徹底表達做者真正想表達的意思,要是被誤導了不是表示很虧,因此吧,從微軟學習後,再看其餘文章,你會了解得更準確更多。

固然先從基礎的學上,看看微軟官方是怎麼說的吧。

http://msdn.microsoft.com/zh-cn/library/yhzc935f(v=vs.100).aspx

 

看完以後,相信你應該會根據這個步驟建立簡單的自定義控件了,至少改變一個Label的輸出內容是沒有問題了,若是咱們想寫一個登錄的自定義控件,看完第一篇後,是否是表示無從下手啦?是的,我看完以後,表示非常無奈,沒事,一步一步來,後面咱們將學到這部分知識。

 

看完微軟官方實例以後啊,我以爲有幾個東西很是重要,容許重複囉嗦來強調下:

咱們看到代碼中有幾個特性:

 

     [
        Bindable(true),
        Category("Appearance"),
        DefaultValue(""),
        Description("The text to display when the user is not logged in."),
        Localizable(true)
        ]
        public virtual string DefaultUserName
        {
            get
            {
                string s = (string)ViewState["DefaultUserName"];
                return (s == null) ? String.Empty : s;
            }
            set
            {
                ViewState["DefaultUserName"] = value;
            }
        }

  

BindableAttribute . 此特性指定將屬性綁定到數據對可視化設計器是否有意義。 例如,在 Visual Studio 中,若是屬性標記爲 Bindable(true),則該屬性可顯示在「數據綁定」對話框中。 若是屬性沒有使用此特性標記,則屬性瀏覽器會推斷其值爲 Bindable(false)。

CategoryAttribute . 此特性指定如何在可視化設計器的屬性瀏覽器中對屬性進行分類。 例如,當頁開發人員使用屬性瀏覽器的分類視圖時,Category("Appearance") 將告知屬性瀏覽器在「外觀」類別中顯示屬性。 能夠指定一個對應於屬性瀏覽器中的現有類別的字符串參數,也能夠建立本身的類別。

DescriptionAttribute . 此特性指定屬性的簡短描述。 在 Visual Studio 中,屬性瀏覽器將在「屬性」窗口底部顯示選定的屬性的描述。<這個我在控件屬性中沒有看到,不曉得是什麼地方錯了>

DefaultValueAttribute . 此特性指定屬性的默認值。 此值應與從屬性訪問器 (getter) 返回的默認值相同。 在 Visual Studio 中,DefaultValueAttribute 特性容許頁開發人員經過在「屬性」窗口中顯示快捷菜單,而後單擊「重置」按鈕將屬性值重置爲其默認值。

LocalizableAttribute . 此特性指定本地化屬性對可視化設計器是否有意義。 當某屬性標記爲 Localizable(true) 時,可視化設計器會在將屬性序列化爲資源時包含該屬性值。 對控件輪詢可本地化的屬性時,設計器會將此屬性值保存到非特定於區域性的資源文件或另外一個本地化源中。

 

ViewState:

用於兩個屬性的 Get 和 Set 方法都利用 ViewState 對象。ViewState 對象是一個內置到 WebControl 類中的幫助器對象。從開發角度講,ViewState 可被視爲一個集合類,用於存儲在回發過程當中咱們想要保留的任意屬性。實際上,ViewState 封裝了肯定如何執行持久性(使用 Cookie、會話等等)所需的全部代碼和邏輯。

 

protected override void RenderContents(HtmlTextWriter writer),

這裏就是設計到控件的生命週期了。控件生命週期的Render階段, 主要將控件標記和字符文本輸出到 服務器控件輸出流 中. 能夠直接寫Html標記, 也能夠調用每一個控件都有的RenderControl方法到輸出流. 在WebControl基類中, 以Render開頭的呈現方法有以下幾個:


RenderControl(HtmlTextWriter writer)

Render(HtmlTextWriter writer)

RenderBeginTag(HtmlTextWriter writer)

RenderContents(HtmlTextWriter output)

RenderEndTag(HtmlTextWriter writer)

 

  

以上幾Render方法中, 並非毫無聯繫的, 它們的執行順序是從上往下, 且有嵌套的調用關係. 其中在RenderControl方法內部會調用Render方法, 在Render方法內部會依次調用RenderBeginTag, RenderContents和RenderEndTag.

其中RenderControl和Render是Control基類中的方法, 由於WebControl自己也是繼承Control的. 通常在開發基本控件時, 咱們只需求重寫RenderContents方法便可, 在此方法中能夠把控件Html文本標記和其它內容寫到輸出流中. 

另外, 還有兩個能夠重載的方法 RenderBeginTag和RenderEndTag, 這兩個方法執行時刻點是分別在Render控件內容以前和以後. 能夠重寫這兩個方法自已定義控件的起始和結束標記. 默認狀況下控件是以<Span></Span>做爲控件起始和結束標記的, 下面是沒有重寫標記的一個例子的默認顯示

 

這裏先看到這個理論知識,後面咱們來實踐下。

 

經過這個章節的學習,知道了如何建立與部署到web的整個流程,那麼剩下的,就是怎麼樣作更好更強大的自定義控件了。

 

我把網頁中的Label,經過反射找到源代碼,供咱們參考了,咱們本身編寫控件,實際上是差很少的

// Generated by .NET Reflector from C:\windows\Microsoft.Net\assembly\GAC_64\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll
namespace System.Web.UI.WebControls
{
    using System;
    using System.ComponentModel;
    using System.Runtime;
    using System.Web;
    using System.Web.UI;
    using System.Web.Util;
    
    [Designer("System.Web.UI.Design.WebControls.LabelDesigner, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ToolboxData("<{0}:Label runat=\"server\" Text=\"Label\"></{0}:Label>"), DataBindingHandler("System.Web.UI.Design.TextDataBindingHandler, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ParseChildren(false), ControlValueProperty("Text"), ControlBuilder(typeof(LabelControlBuilder)), DefaultProperty("Text")]
    public class Label : WebControl, ITextControl
    {
        private bool _textSetByAddParsedSubObject;
        
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        public Label()
        {
        }
        
        [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
        internal Label(HtmlTextWriterTag tag) : base(tag)
        {
        }
        
        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            string associatedControlID = this.AssociatedControlID;
            if (associatedControlID.Length != 0)
            {
                if (this.AssociatedControlInControlTree)
                {
                    Control control = this.FindControl(associatedControlID);
                    if (control == null)
                    {
                        if (!base.DesignMode)
                        {
                            throw new HttpException(SR.GetString("LabelForNotFound", new object[] { associatedControlID, this.ID }));
                        }
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.For, control.ClientID);
                    }
                }
                else
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.For, associatedControlID);
                }
            }
            base.AddAttributesToRender(writer);
        }
        
        protected override void AddParsedSubObject(object obj)
        {
            if (this.HasControls())
            {
                base.AddParsedSubObject(obj);
            }
            else if (obj is LiteralControl)
            {
                if (this._textSetByAddParsedSubObject)
                {
                    this.Text = this.Text + ((LiteralControl) obj).Text;
                }
                else
                {
                    this.Text = ((LiteralControl) obj).Text;
                }
                this._textSetByAddParsedSubObject = true;
            }
            else
            {
                string text = this.Text;
                if (text.Length != 0)
                {
                    this.Text = string.Empty;
                    base.AddParsedSubObject(new LiteralControl(text));
                }
                base.AddParsedSubObject(obj);
            }
        }
        
        protected override void LoadViewState(object savedState)
        {
            if (savedState != null)
            {
                base.LoadViewState(savedState);
                if ((((string) this.ViewState["Text"]) != null) && this.HasControls())
                {
                    this.Controls.Clear();
                }
            }
        }
        
        protected internal override void RenderContents(HtmlTextWriter writer)
        {
            if (base.HasRenderingData())
            {
                base.RenderContents(writer);
            }
            else
            {
                writer.Write(this.Text);
            }
        }
        
        [Themeable(false), WebSysDescription("Label_AssociatedControlID"), DefaultValue(""), IDReferenceProperty, TypeConverter(typeof(AssociatedControlConverter)), WebCategory("Accessibility")]
        public virtual string AssociatedControlID
        {
            get
            {
                string str = (string) this.ViewState["AssociatedControlID"];
                if (str != null)
                {
                    return str;
                }
                return string.Empty;
            }
            set
            {
                this.ViewState["AssociatedControlID"] = value;
            }
        }
        
        internal bool AssociatedControlInControlTree
        {
            get
            {
                object obj2 = this.ViewState["AssociatedControlNotInControlTree"];
                if (obj2 != null)
                {
                    return (bool) obj2;
                }
                return true;
            }
            set
            {
                this.ViewState["AssociatedControlNotInControlTree"] = value;
            }
        }
        
        internal override bool RequiresLegacyRendering
        {
            get
            {
                return true;
            }
        }
        
        public override bool SupportsDisabledAttribute
        {
            get
            {
                return (this.RenderingCompatibility < VersionUtil.Framework40);
            }
        }
        
        protected override HtmlTextWriterTag TagKey
        {
            get
            {
                if (this.AssociatedControlID.Length != 0)
                {
                    return HtmlTextWriterTag.Label;
                }
                return base.TagKey;
            }
        }
        
        [Localizable(true), PersistenceMode(PersistenceMode.InnerDefaultProperty), Bindable(true), WebCategory("Appearance"), DefaultValue(""), WebSysDescription("Label_Text")]
        public virtual string Text
        {
            get
            {
                object obj2 = this.ViewState["Text"];
                if (obj2 != null)
                {
                    return (string) obj2;
                }
                return string.Empty;
            }
            set
            {
                if (this.HasControls())
                {
                    this.Controls.Clear();
                }
                this.ViewState["Text"] = value;
            }
        }
    }
}

 

這裏有個網頁寫得不錯,看完後,但願你能收穫更多.

http://blog.csdn.net/huang7914/article/details/2329261

相關文章
相關標籤/搜索