1 . 继承control类:一般不可见html元素主要是继承control类,比如meta中的元素或者隐藏域等 2 .继承webcontrol类:一般可见元素比如 < input type = text > 等,为了获取更多的样式支持,减少代码量,一般直接继承webcontrol:比如分页控件等:http: // blog.csdn.net/46539492/archive/2008/04/02/2244627.aspx 3 .复合控件:定义复合控件一般要继承INamingContainer这个接口。比如一个简单用户登陆控件http: // blog.csdn.net/46539492/archive/2008/03/14/2182934.aspx 4 .数据列表控件:比如DropDownList,CheckBoxList等控件一般继承ListControl,又因为这些控件存在数据传输或者说数据回发,则要继承IPostBackDataHandler接口。 5 .复合列表控件比如CheckBoxList,RadioButtonList等控件,除了继承ListControl类,IPostBackDataHandler接口外,还要实现IRepeatInfoUser接口,IRepeatInfoUser接口定义了重复项列表的列表控件实现的属性和方法,最后还因为他们是复合控件,还要继承INamingContainer接口6.数据绑定控件 ( 1 )DataListDataList类似于CheckBoxList,是重复项列表的列表控件,所以需要继承IRepeatInfoUser,也是复合控件,所以继承INamingContainer接口,此外还要继承BaseDataList类,该类用数据列表控件的基类,如DataList和DataGrid,该类提供所有数据列表控件的所有方法和属性。( 2 )RepeaterRepeater比较灵活,继承control和INamingContainer接口。( 3 )DataGridDataGrid类,和DataList类似,主要继承BaseDataList类和INamingContainer接口( 4 )GridViewGridView是比较复杂的数据绑定控件,继承CompositeDataBoundControl, IPostBackContainer, IPostBackEventHandler, ICallbackContainer, ICallbackEventHandler其中CompositeDataBoundControl表示由其他服务器控件组成的表格数据绑定控件的基类; IPostBackContainer接口定义一个方法;使控件能够获取客户端脚本选项。ICallbackContainer接口定义一个方法,使控件能够获取回调脚本;ICallbackEventHandler用于指示控件可以作为服务器的回调事件的目标。 6 .导航控件( 1 )TreeView控件TreeView控件主要继承HierarchicalDataBoundControl, IPostBackEventHandler, IPostBackDataHandler, ICallbackEventHandler,其中HierarchicalDataBoundControl用作所有 ASP.NET 2.0 版数据绑定控件的基类,这些控件以分层形式显示它们的数据。因为有数据回发所以继承IPostBackDataHandler,继承IPostBackEventHandler处理回发事件,和GridView类似,ICallbackEventHandler用于指示控件可以作为服务器的回调事件的目标( 2 )Menu控件Menu主要继承HierarchicalDataBoundControl, IPostBackEventHandler, INamingContainer,因为Menu是个复合控件,继承INamingContainer接口。二、样式相关 1 . 重写TagKey示例如下: 重写TagKey 重写TagKey #region 重写TagKey protected override HtmlTextWriterTag TagKey ......{ get ......{ return HtmlTextWriterTag.Table; } } #endregion 默认是HtmlTextWriterTag.Span,当需要其它标签时,需要重写TagKey,比如以下代码: < table width = " 100% " style = " height:20px; border:solid 1px #cccccc; " cellpadding = " 0 " cellspacing = " 0 " > < tr > < td align = " right " > 当前第 < asp:Label ID = " lblCurrentPage " runat = " server " ></ asp:Label > 页, 总共 < asp:Label ID = " lblRecodeCount " runat = " server " ></ asp:Label > 条纪录, 共 < asp:Label ID = " lblPageCount " runat = " server " ></ asp:Label > 页, < asp:Label ID = " Label1 " runat = " server " ></ asp:Label > < asp:LinkButton ID = " lnkbtnFrist " runat = " server " OnClick = " lnkbtnFrist_Click " >< font face = webdings color = " red " > 9 </ font ></ asp:LinkButton > < asp:LinkButton ID = " lnkbtnPre " runat = " server " OnClick = " lnkbtnPre_Click " >< font face = webdings color = " red " > 7 </ font ></ asp:LinkButton > < asp:LinkButton ID = " lnkbtnNext " runat = " server " OnClick = " lnkbtnNext_Click " >< font face = webdings color = " red " > 8 </ font ></ asp:LinkButton > < asp:LinkButton ID = " lnkbtnLast " runat = " server " OnClick = " lnkbtnLast_Click " >< font face = webdings color = " red " > : </ font ></ asp:LinkButton > 跳转到第 < asp:TextBox ID = " txtPageIndex " runat = " server " style = " width:40px; " onkeypress = " myKeyDown(); " ></ asp:TextBox > 页 < asp:Button ID = " BtnChangePage " runat = " server " Text = " GO " OnClick = " BtnChangePage_Click " /> </ td > </ tr > </ table > 这段代码要写成控件,就需要重写TaGKey,改为HtmlTextWriterTag.Table。然后绘制控件: 绘制控件 绘制控件 #region 绘制控件 protected override void RenderContents(HtmlTextWriter writer) ......{ if (ButtonStyle != null) ......{ _btnChangePage.ApplyStyle(ButtonStyle); } if (TextBoxStyle != null) ......{ _txtPageIndex.ApplyStyle(TextBoxStyle); } if (LabelStyle != null) ......{ _lblCurrentPage.ApplyStyle(LabelStyle); _lblPageCount.ApplyStyle(LabelStyle); _lblRecodeCount.ApplyStyle(LabelStyle); _lblPageSize.ApplyStyle(LabelStyle); } AddAttributesToRender(writer); writer.RenderBeginTag(HtmlTextWriterTag.Tr); writer.AddAttribute(HtmlTextWriterAttribute.Align, "right"); writer.RenderBeginTag(HtmlTextWriterTag.Td); writer.Write("当前第"); if (_lblCurrentPage != null) _lblCurrentPage.RenderControl(writer); writer.Write("页,每页"); if (_lblPageSize != null) ......{ _lblPageSize.RenderControl(writer); } writer.Write("条纪录,总共"); if (_lblRecodeCount != null) _lblRecodeCount.RenderControl(writer); writer.Write("条纪录,共"); if (_lblPageCount != null) _lblPageCount.RenderControl(writer); writer.Write("页 [ "); if (_lnkbtnFrist != null) ......{ if (PageIndex == 1) //如果是第一页,则第一页灰显,作用是避免不必要的点击造成没必要的数据传输 ......{ _lnkbtnFrist.Enabled = false; } else ......{ _lnkbtnFrist.Enabled = true; } _lnkbtnFrist.RenderControl(writer); } writer.Write(" "); if (_lnkbtnPre != null) ......{ if (PageIndex > 1) //如果当前页大于1,则上一页显示,否则灰显 ......{ _lnkbtnPre.Enabled = true; } else ......{ _lnkbtnPre.Enabled = false; } _lnkbtnPre.RenderControl(writer); } writer.Write(" "); if (_lnkbtnNext != null) ......{ if (_lblPageCount == null) ......{ _lnkbtnNext.Enabled = false; } else ......{ int pageCount = int.Parse(_lblPageCount.Text); //获取总页数 if (PageIndex < pageCount)//如果当前页小于总页数,则下一页显示,否则灰显 ......{ _lnkbtnNext.Enabled = true; } else ......{ _lnkbtnNext.Enabled = false; } } _lnkbtnNext.RenderControl(writer); } writer.Write(" "); if (_lnkbtnLast != null) ......{ if (_lblPageCount == null) ......{ _lnkbtnLast.Enabled = false; } else ......{ int pageCount = int.Parse(_lblPageCount.Text); //获取总页数 if (PageIndex == pageCount)//如果当前页为最后一页,则末页灰显 ......{ _lnkbtnLast.Enabled = false; } else ......{ _lnkbtnLast.Enabled = true; } } _lnkbtnLast.RenderControl(writer); } writer.Write(" ]跳转到第"); if (_txtPageIndex != null) _txtPageIndex.RenderControl(writer); writer.Write("页"); if (_btnChangePage != null) _btnChangePage.RenderControl(writer); writer.RenderEndTag(); writer.RenderEndTag(); //base.RenderContents(writer); } #endregion }} 2 .重写CreateControlStyle重写CreateControlStyle,可以根据需要应用相关的样式,比如继承Label类,并重写CreateControlStyle方法,使该控件具有表格的样式: protected override Style CreateControlStyle() ... ... { return new TableStyle(ViewState); } [BrowsableAttribute( true )] [DescriptionAttribute( " 网格线 " )] [CategoryAttribute( " Appearance " )] public virtual GridLines GridLines ... ... { get ......{ return ((TableStyle)ControlStyle).GridLines; } set ......{ ((TableStyle)ControlStyle).GridLines = value; } } 这样该自定义的label就具有表格的样式,比如网格线。 3 .继承webcontrol通过继承webcontrol类可以获得webcontrol类很多样式,比如: 4 .通过继承Style类来自定义Style示例如下: using System; using System.Collections.Generic; using System.Text; using System.Web; using System.ComponentModel; using System.Web.UI.WebControls; using System.Web.UI; namespace MyLabel... ... { public class LabelStyle:Style ......{ public LabelStyle() ......{ } public LabelStyle(StateBag viewState) : base(viewState) ......{ } public virtual String ImageUrl ......{ get ......{ return ViewState["imageUrl"] != null ? (string)ViewState["imageUrl"] : ""; } set ......{ ViewState["imageUrl"] = value; } } //判断视图状态是否为空 internal bool IsSet(string key) ......{ return ViewState[key] != null; } /**//**//**//**/ /**//**//**//// <summary> /// 是否定义样式元素 /// </summary> public override bool IsEmpty ......{ get ......{ return base.IsEmpty && !IsSet("imageUrl"); } } public override void AddAttributesToRender(HtmlTextWriter writer, WebControl owner) ......{ writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundImage, ImageUrl); base.AddAttributesToRender(writer, owner); } }} 使用方法: using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace MyLabel... ... { public class MyLabel3:Label ......{ protected override Style CreateControlStyle() ......{ return new LabelStyle();//使用自定义的Style } [DefaultValue("")] public virtual string ImageUrl ......{ get ......{ return ((LabelStyle)ControlStyle).ImageUrl; } set ......{ ((LabelStyle)ControlStyle).ImageUrl = value; } } }} 三、属性相关 1 .简单属性简单属性是指属性值可以很容易转换为字符串表达式的属性,这种属性的值通常为Boolean、Byte、Char、Double、Enum、Int32、DateTime等简单数值类型,以及String类型和枚举类型。开发人员可以通过添加代码,将简单属性存储在ViewState字典中,以在回发间进行状态管理。通常的示例如下: [Browsable( true )] [Category( " Appearance " )] [Description( " 设置单击当前行时当前行的背景色 " )] public virtual Color ClickBackGroundColor ... ... { get ......{ return ViewState["ClickBackGroundColor"]!=null?(Color)ViewState["ClickBackGroundColor"]:Color.Empty; } set ......{ ViewState["ClickBackGroundColor"] = value; } } 2 .复杂属性如果一个属性的类型是本身具有属性(称为子属性)的类,则该属性就称为复杂属性。例如,WebControl类的Font属性的类型是本身具有属性(如Bold和Name)的FontInfo类。Bold和Name是WebControl的Font属性的子属性。复杂属性不能简单的用ViewState来进行状态管理,需要自定义视图状态,比如我前一篇文章《千万级数据分页之二 --- 一个简单的自定义分页控件》定义的ButtonStyle,TextBoxStyle等就属于复杂属性: 样式属性 样式属性 #region 样式属性 private Style _buttonStyle; private Style _textBoxStyle; private Style _linkButtonStyle; [ Category("Styles"), DefaultValue(null), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty), Description( "应用于按钮的样式") ] public virtual Style ButtonStyle ......{ get ......{ if (_buttonStyle == null) ......{ _buttonStyle = new Style(); if (IsTrackingViewState) ......{ ((IStateManager)_buttonStyle).TrackViewState(); } } return _buttonStyle; } } [ Category("Styles"), DefaultValue(null), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty), Description( "应用于链接按钮的样式") ] public virtual Style LinkButtonStyle ......{ get ......{ if (_linkButtonStyle == null) ......{ _linkButtonStyle = new Style(); if (IsTrackingViewState) ......{ ((IStateManager)_linkButtonStyle).TrackViewState(); } } return _linkButtonStyle; } } [ Category("Styles"), DefaultValue(null), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty), Description( "应用于文本框的样式") ] public virtual Style TextBoxStyle ......{ get ......{ if (_textBoxStyle == null) ......{ _textBoxStyle = new Style(); if (IsTrackingViewState) ......{ ((IStateManager)_textBoxStyle).TrackViewState(); } } return _textBoxStyle; } } private Style _labelStyle; [ Category("Styles"), DefaultValue(null), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty), Description( "应用于标签的样式") ] public virtual Style LabelStyle ......{ get ......{ if (_labelStyle == null) ......{ _labelStyle = new Style(); if (IsTrackingViewState) ......{ ((IStateManager)_labelStyle).TrackViewState(); } } return _labelStyle; } } #endregion 自定义视图状态 自定义视图状态 #region 自定义视图状态 protected override void LoadViewState(object savedState) ......{ if (savedState == null) ......{ base.LoadViewState(null); return; } else ......{ Triplet t = savedState as Triplet; if (t != null) ......{ base.LoadViewState(baseState); if ((t.Second) != null) ......{ ((IStateManager)ButtonStyle).LoadViewState(buttonStyleState); } if ((t.Third) != null) ......{ ((IStateManager)TextBoxStyle).LoadViewState(textBoxStyleState); } if (labelStyleState != null) ......{ ((IStateManager)(_labelStyle)).LoadViewState(labelStyleState); } if (linkButtonStyleState != null) ......{ ((IStateManager)(_linkButtonStyle)).LoadViewState(linkButtonStyleState); } } else ......{ throw new ArgumentException("Invalid view state ."); } } } protected override object SaveViewState() ......{ baseState = base.SaveViewState(); buttonStyleState = null; textBoxStyleState = null; labelStyleState = null; linkButtonStyleState = null; if (_buttonStyle != null) ......{ buttonStyleState = ((IStateManager)_buttonStyle).SaveViewState(); } if (_textBoxStyle != null) ......{ textBoxStyleState = ((IStateManager)_textBoxStyle).SaveViewState(); } if (_labelStyle != null) ......{ labelStyleState = ((IStateManager)_labelStyle).SaveViewState(); } if (_linkButtonStyle != null) ......{ linkButtonStyleState = ((IStateManager)_linkButtonStyle).SaveViewState(); } return new Triplet(baseState, buttonStyleState, textBoxStyleState); } protected override void TrackViewState() ......{ base.TrackViewState(); if (_buttonStyle != null) ......{ ((IStateManager)_buttonStyle).TrackViewState(); } if (_textBoxStyle != null) ......{ ((IStateManager)_textBoxStyle).TrackViewState(); } if (_labelStyle != null) ......{ ((IStateManager)_labelStyle).TrackViewState(); } if (_linkButtonStyle != null) ......{ ((IStateManager)_linkButtonStyle).TrackViewState(); } } #endregion