asp.net|服务器|控件|控件开发
随着.NET技术的不断发展和成熟,服务器控件越来越受到广大开发人员的喜爱。同时,服务器控件的发展也呈现出一些趋势,例如,功能越来越强大,很多功能逐渐从服务器端转移到客户端。另外,服务器控件也越来越美观。这可能与Windows操作系统越来越讲求功能与外观统一的发展思路有关。本文及其随后的几篇文章将重点介绍如何为服务器控件实现漂亮的外观。实际上,服务器控件的外观主要由样式属性决定。本文重点对实现控件样式的基本知识进行概括性讲解。
服务器控件样式简介
对于普通应用开发人员而言,只需要知道服务器控件具有哪些样式属性,并了解每一个样式属性可能为控件外观带来的影响即可。例如,如果需要修改页面背景颜色,则需要修改样式属性BackgroundColor值;如果需要设置表格对象外观,那么可能需要设置BorderColor、BorderWidth等样式属性。然而,对于一名控件开发人员而言,他们不仅需要掌握应用开发人员所掌握的相关知识,而且还必须了解构建控件样式属性的创建方法。
通常,具有样式属性的服务器控件均继承自System.Web.UI.WebControl基类。这样,控件类可自动继承基类中的多个样式属性。这些样式属性包括获取或者设置控件背景颜色的BackColor、获取或者设置控件前景颜色的ForeColor、获取或者设置控件边框颜色的BorderColor、获取或者设置控件边框样式的BorderStyle等等。如果控件类从WebControl基类继承,那么这些样式属性可自动得到继承,并且允许开发人员根据具体情况,对这些样式属性进行重写。另外,如果控件类继承自其他现有控件类,例如 GridView,那么自定义控件将自动继承GridView基类的样式属性,如设置交替数据行样式的AlternatingRowStyle、设置正在编辑的数据行的样式EditRowStyle等等。很显然,这些继承自已有服务器控件的样式属性并非此处要讨论的重点。然而,读者应了解样式属性允许从基类继承并无需修改即可直接使用的。下面继续讨论WebControl类中的样式属性。
WebControl类的样式均封装在ControlStyle属性中。该属性值是Style数据类型。为了更好的了解ControlStyle,下面列举了ControlStyle属性的定义代码。
private Style _controlStyle;
//定义ControlStyle属性
public Style ControlStyle{
get {
if(_controlStyle == null) {
_controlStyle = CreateControlStyle();
if(IsTrackingViewState) {
((IStateManager)_controlStyle).TrackViewState();
}
}
}
}
//定义CreateControlStyle方法
protected virtual Style CreateControlStyle(){ return new Style(ViewState);}
如上代码所示,ControlStyle是一个只读属性,其数据类型为Style。当第一次访问该属性的时候被创建,其过程为:首先,判断_controlStyle是否为空,如果为空,则调用CreateControlStyle方法来创建_controlStyle对象,即一个Style的实例。然后,执行视图状态跟踪任务,其具体过程由Style类所提供的TrackViewState方法来完成。
在初步了解ControlStyle属性之后,接着我们应了解与该属性密切相关的Style类。
Style类用于表示服务器控件的样式,其包括以下几个属性:
(1)BackColor,获取或者设置Web服务器控件的背景色;
(2)BorderColor,获取或者设置控件的边框颜色;
(3)BorderStyle,获取或者设置控件的边框样式;
(4)BorderWidth,获取或者设置控件的边框宽度;
(5)CssClass,获取或者设置控件在客户端呈现的级联样式表类;
(6)Font,获取与控件关联的字体属性;
(7)ForeColor,获取或者设置控件的前景颜色;
(8)Height,获取或者设置控件的高度;
(9)IsEmpty,获取一个值,该值指示是否已经在ViewState中定义任何样式元素;
(10)IsTrackingViewState,返回一个值,该值指示是否正在跟踪其视图状态的更改。
(11)RegisteredCssClass,获取已向控件注册的级联样式表类;
(11)ViewState,获取保存样式元素的视图状态。
另外,Style类中还包括一些成员方法。利用它们可以很方便的对样式进行操作。下面列举了来自WebControl和Style类的,用于实现样式操作的方法。
(1)protected virtural Style CreateControlStyle()
创建由WebControl类在内部用来实现所有与样式有关的属性的样式对象。
(2)public void ApplyStyle(Style s)
将指定样式的所有非空白元素复制到服务器控件,改写控件的所有现有的样式元素。其中s表示要复制的样式。
(3)public void MergeStyle(Style s)
将指定样式的所有非空白元素复制到服务器控件,但不改写该控件现有的任何样式元素。其中s表示要复制的样式。
以上三个方法均来自WebControl类。下面两个方法来自Style类。
(4)public virtual void CopyFrom(Style s)
将指定的Style的样式属性复制到从中调用此方法的Style类的实例中。s表示要复制的样式的Style。使用此方法Style类的当前实例中的所有属性都将替换为s参数指定的Style中的关联属性。
(5)public virtual void MergeWith(Style s)
将指定Style的样式属性与从中调用此方法的Style类的实例组合。其中s表示要合并的样式的Style。此方法通过将每个在Style类的当前实例中未设置的属性设置为s参数指定的Style的对应属性中的值,将两个Style对象的属性联接起来。只有尚未设置的属性将被替换。如果没有设置s参数中的属性,则它将不替换Style类的当前实例中的对应属性。
为了帮助读者加深对于以上方法的理解,下面列举了一段示例代码。
//定义两个Style对象实例
Style s1 = new Style();
Style s2 = new Style();
//分别为s1和s2定义ForeColor属性值
s1.ForeColor = Color.Red;
s2.ForeColor = Color.White;
//调用相关方法
s1.CopyFrom(s2);
s1.MergeFrom(s2);
上面的代码比较简单。Style对象实例s1在调用CopyFrom方法之后,其ForeColor的属性值将被修改为Color.White;s1在调用MergeFrom之后,其ForeColor的属性值则不变,仍然为Color.Red。
重写样式属性
样式属性的重载与其他属性的重载没有什么区别。然而,在实现过程中必须注意的是,对属性值所作的修改必须上传给控件的ControlStyle属性。下面列举了一个示例应用程序,其重写了Table控件的样式属性CellSpacing和Caption。服务器控件源代码如下所示。
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{
[DefaultProperty("Text")]
[ToolboxData("<{0}:WebCustomControl runat=server></{0}:WebCustomControl>")]
public class WebCustomControl : Table {
//创建构造函数
public WebCustomControl() {
base.Caption = "工作安排列表";
base.CellSpacing = 0;
}
// 重写CellSpacing属性
[ Bindable(false), Browsable(false), DefaultValue(0) ]
public override int CellSpacing {
get {
return base.CellSpacing;
}
set {
throw new NotSupportedException("不能设置CellSpacing属性.");
}
}
//重写Caption属性
[DefaultValue("工作安排列表")]
public override string Caption {
get { return base.Caption; }
set { base.Caption = value; }
}
}
}
以上代码主要用于说明重写样式属性的实现方法。具体分析如下所示。
(1)控件类WebCustomControl继承自Table。这样,自定义控件则自动继承了Table控件所具有的所有样式属性。这为重写样式属性奠定了基础。
(2)在控件类的构造函数中设置了Caption和CellSpacing的属性值。
(3)重写CellSpacing属性。通过元数据属性标记设置了该属性不可被数据绑定(Bindable),告诉设计器该属性不可被浏览(Browsable),最后设置了默认值为0(DefaultValue)。另外,在CellSpacing属性的设置操作中定义了一个异常。当开发人员设置该属性时将显示该异常。
(4)重写Caption属性,为该属性设置默认值。
可能有些读者认为构造函数的设置内容没有什么意义。实际上,实现本例的核心就在于此。只有在构造函数中设置新的属性值,才能够将新值传递给ControStyle属性。因为ControlStyle属性主要完成的工作是负责样式状态管理以及样式属性的生成。如果没有把改变传到ControlStyle,那么重写的样式属性就不会按照预期的那样显示。
下面列举了为测试自定义控件WebCustomControl而创建的Default.aspx页面源代码。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register TagPrefix="wcc" Namespace="WebControlLibrary" Assembly="WebControlLibrary" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>重写样式属性</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<wcc:WebCustomControl ID="demo1" runat="server" Font-Size="small" BorderWidth="1px" CellPadding="4" BorderColor="black" GridLines="both">
<asp:TableRow>
<asp:TableCell font-bold="True" runat="server">工作项目</asp:TableCell>
<asp:TableCell font-bold="True" runat="server">截至日期</asp:TableCell>
<asp:TableCell font-bold="True" runat="server">备注</asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server">
<asp:TableCell runat="server">工作1</asp:TableCell>
<asp:TableCell runat="server">7月17日</asp:TableCell>
<asp:TableCell runat="server">备注内容</asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server">
<asp:TableCell runat="server">工作2</asp:TableCell>
<asp:TableCell runat="server">7月27日</asp:TableCell>
<asp:TableCell runat="server">备注内容</asp:TableCell>
</asp:TableRow>
<asp:TableRow runat="server">
<asp:TableCell runat="server">工作3</asp:TableCell>
<asp:TableCell runat="server">7月29日</asp:TableCell>
<asp:TableCell runat="server">备注内容</asp:TableCell>
</asp:TableRow>
</wcc:WebCustomControl>
</div>
</form>
</body>
</html>
下面显示了示例应用效果图。
根据Default.aspx源代码以及应用效果图可知,上图中的表格标题(Caption),以及相邻表格间距(CellSpacing)均由自定义控件内置设置,而不是通过控件的显式标记来完成。这就是重写控件样式属性的结果。
小结
本文首先对服务器控件样式的基本知识进行了简要介绍,然后,通过一个典型示例说明了重写控件样式属性的方法。希望读者通过这些内容,能够对服务器控件样式属性建立一个更为深入的理解。在随后的文章中,我们将讲解实现样式属性的具体方法。