asp.net组件设计总结
2008-04-06 14:37
429 查看
一、关于继承方面
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)DataList
DataList类似于CheckBoxList,是重复项列表的列表控件,所以需要继承IRepeatInfoUser,也是复合控件,所以继承INamingContainer接口,此外还要继承BaseDataList类,该类用数据列表控件的基类,如DataList和DataGrid,该类提供所有数据列表控件的所有方法和属性。
(2)Repeater
Repeater比较灵活,继承control和INamingContainer接口。
(3)DataGrid
DataGrid类,和DataList类似,主要继承BaseDataList类和INamingContainer接口
(4)GridView
GridView是比较复杂的数据绑定控件,继承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#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
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)DataList
DataList类似于CheckBoxList,是重复项列表的列表控件,所以需要继承IRepeatInfoUser,也是复合控件,所以继承INamingContainer接口,此外还要继承BaseDataList类,该类用数据列表控件的基类,如DataList和DataGrid,该类提供所有数据列表控件的所有方法和属性。
(2)Repeater
Repeater比较灵活,继承control和INamingContainer接口。
(3)DataGrid
DataGrid类,和DataList类似,主要继承BaseDataList类和INamingContainer接口
(4)GridView
GridView是比较复杂的数据绑定控件,继承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#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
相关文章推荐
- asp.net组件设计总结
- ASP.NET组件设计Step by Step
- 【商业版】2010年ASP.NET C#通用权限管理系统组件源码销售100套以上的经验总结【2011年配套源码要涨价了】
- ASP.NET组件设计DOC
- [读书笔记][深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白
- Asp.net项目经验总结之一 设计与规划
- ASP.NET 2.0服务器控件与组件开发高级编程:为自定义控件添加设计时属性
- ASP.NET组件设计Step by Step(3)
- ASP.NET组件设计Step by Step(5)
- 【转载】Asp.NET大文件上传组件开发总结(四)---封送数据给Asp.NET页面
- ASP.NET组件设计Step by Step(8)
- 销售C#ASP.NET通用权限管理系统组件源码经验总结:软件源码能卖钱【收钱也很累】
- Asp.net组件设计浅论
- ASP.NET组件设计Step by Step(3)
- Asp.NET大文件上传组件开发总结(四)---封送数据给Asp.NET页面
- ASP.NET组件设计Step by Step(4)
- ASP.NET组件设计Step by Step(5)
- Asp.net组件设计浅论(转)
- ASP.NET组件设计Step by Step(2)
- 温故之新(asp.net组件设计)序