上一篇文章对控件样式属性的基本概念进行了介绍,同时,还通过示例说明了重写样式属性的方法。本文重点对类型化样式属性的创建方法进行讲解。
实现类型化样式属性的方法
继承自Style类的类称为类型化样式。Style类可以由控件开发人员来扩展,创建一个自定义类型化样式,它重写或者添加Style类的属性。服务器控件也可以把自定义类型化样式作为ControlStyle属性的类型。例如,Table控件的ControlStyle属性就是TableStyle类型,该类型是扩展的Style,添加了例如CellPadding、CellSpacing和GridLines属性等。在初步了解类型化样式属性的基本概念之后,下面列举了实现类型化样式属性的方法要点。
(1)创建一个派生自System.Web.UI.WebControls.Style的类;
(2)定义样式将为控件提供的属性。在Style的ViewState字典中保存该属性;
(3)重写CopyFrom和MergeWith方法,从定义的属性中复制或者将定义的属性和一个给定样式的属性合并;
(4)重写Reset方法,删除添加到ViewState中的属性;
(5)重写AddAttributesToRender方法,产生HTML和CSS特性,作为控件呈现过程的一部分。
实际上,创建类型化样式属性并不是一个简单的过程。为此,下面我们将通过典型应用示例来说明创建的具体方法,以便读者加深对于实现要点的理解。
典型应用
本节通过创建一个MyPanel控件以及相关联的类型化样式MyPanelStyle,来讲解如何实现并使用自定义类型化样式。就功能而言,MyPanel与ASP.NET 2.0内置的Panel控件是一致。开发人员可以通过把需要添加的控件嵌套在控件的标签中,向Controls集合中添加控件。在可视化设计器中,把所需添加的控件拖放到Panel的设计界面上,就可以把控件添加到Controls集合中。然而,MyPanel并不是从Panel类继承而来,而是自定义实现的结果,同时,该控件还提供了类型化样式属性MyPanelStyle,其中设置了3个样式属性:
(1)BackImageUrl,用于指定背景图片的URL;
(2)HorizontalAlign,用于指定所添加内容的水平对其方式;
(3)Wrap,用于指定是否允许对所添加的内容换行。
下面列举了示例效果图。
图1
如图1所示,图中显示了一个MyPanel控件,其中包括一行文字,文字的背景图像已经定义,并且文字处于居中位置。
下面列举了实现自定义服务器控件的MyPanel.cs源代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebControlLibrary{
[ ParseChildren(false), PersistChildren(true) ]
[ToolboxData("<{0}:MyPanel runat=server></{0}:MyPanel>")]
public class MyPanel : WebControl {
// 定义构造函数
public MyPanel() : base(HtmlTextWriterTag.Div) { }
// 实现属性BackImageUrl
[Bindable(true)] [Category("Appearance")]
[DefaultValue("")]
public virtual string BackImageUrl {
get {
if (ControlStyleCreated) {
return ((MyPanelStyle)ControlStyle).BackImageUrl;
}
return String.Empty;
}
set {
((MyPanelStyle)ControlStyle).BackImageUrl = value;
}
}
// 实现属性HorizontalAlign
[Bindable(true)]
[Category("Layout")]
[DefaultValue("")]
public virtual HorizontalAlign HorizontalAlign {
get {
if (ControlStyleCreated) {
return ((MyPanelStyle)ControlStyle).HorizonalAlign;
}
return HorizontalAlign.NotSet;
}
set {
((MyPanelStyle)ControlStyle).HorizonalAlign = value;
}
}
// 实现属性Wrap
[Bindable(true)]
[Category("Layout")]
[DefaultValue("")]
public virtual bool Wrap {
get {
if (ControlStyleCreated) {
return ((MyPanelStyle)ControlStyle).Wrap;
}
return true;
}
set {
((MyPanelStyle)ControlStyle).Wrap = value;
}
}
protected override Style CreateControlStyle() {
return new MyPanelStyle(ViewState);
}
}
}
在分析之前,为了帮助读者更好的阅读以上源代码,下面列举了MyPanel类图。
图2
如上代码所示,MyPanel继承自WebControl基类,其中定义了3个属性BackImageUrl、HorizontalAlign和Wrap。关于这3个属性的说明,读者可参考前面的内容。另外,MyPanel重写了CreateControlStyle方法,返回一个MyPanelStyle对象。这样返回的MyPanelStyle实例间接的赋值给ControlStyle属性。这种实现方法的原因是由于ControlStyle属性是只读属性,且它的访问操作需要调用CreateControlStyle方法时间接进行设置。需要读者注意的是,CreateControlStyle将MyPanel控件的ViewState传递给MyPanelStyl