1、用Visual C#.NET编写服务器日期控件一、序言 Visual C#.nel是微软公司出品的一种新的编程语言(以下简称C#),它继承了 C 语言的一些特性,也加入了一些新的元素。以前用过Delphi开发程序的人可能刚开始 使用C#的时候,对其有•种似曾相识的感觉(至少包括我)。是的,C#语言的创始人正 是以前在Borland公司开发出Delphi语言的Anders Hejlsbergo在我开始使用C#开发 程序时,就觉得它是一款很棒的开发Windows Form & Web程序的RAD工具。 在开发Web程序方面,C#的出现打破了以前的网页开发模式,实现了与开发Windows Fo
2、rm程序一样的所见即所得的功能。C#提供了一些常用的Web Form Control供开 发人员使用,并且只需将控件拖入页面中即可,非常简单。但有时这些控件也不能满足 开发人员的需要,需要开发人员自己编写用户控件(User Control)或自定义控件(Custom Control)来满足需求。在这里,我将讲解如何在C#中开发服务器控件。 二、预备知识 在C#中可以开发两种服务器控件,一个是用户控件(UserControl)和自定义控件 (Custom Control) o用户控件的本质与页面文件(ASPx文件)差不多,是可被其它 aspx页面重复使用的HTML代码段,当然它也包括后台代码
3、Code-behind),后缀名是 asexo所以在开发一些公用的静态页面时(例如页头,页脚)经常用到,但它的缺点是 不易继承,不易分发,无法编译成二进制代码来进行部署。但是白定义控件的功能就强 大许多,它可以被编译成二进制代码(DLL文件),可以被扩展、继承、分发。就像Web Form Control 一样,其实它们每个控件就是一个DLL文件。 开发用户控件比拟简单,就像编写一个aspx页面一样,在这里就不介绍了。本文 对象是自定义控件。服务器控件的基类是System. Web. UI. Control。如果要开发可视化 的服务器控件,那我们需要从System. Web. UI. Web
4、Controls来继承,否那么从 System. Web. UI. Control 继承。 output. AddAttribute(HtmlTextWriterAttribute. Name, DatePickerButtonName);output. AddAttributc(HtmlTcxtWri tcrAttributc. Value, ButtonTcxt): output. .AddStyleAttributeCHtmlTextWriterStyle. Width, "100$");output. AddAttributedltmlTextWri terAttribute. O
5、ncl ick, Page. GetPostBackEventReference(this)): 〃点击按钮时需要回传服务器来触发后面的 OnClick 事件output. .i\dd/\ttribute(HtmlTextWriterAttribute. Style, ButtonStyle): output. RenderBcginTag(HtmlTextWriterTag. Input); //输出按钮output. RenderEndTagO ; output. RenderEndTagO ;output. RenderEndTagO ; output. RenderBeginT
6、ag(HtmlTextWriterTag. Tr);output. AddAttributeOltmlTextWri terAttribute. Col span, "2"); output. RenderBeginTag(HtmlTextWriterTag. Td);Calendar. RenderControl (output); 〃将日历子控件输出 output. RenderEndTagO ;output. RenderEndTagO ; output. RenderEndTagO ; ) 〃复合控件必须继承IpostBackEventHandler接口,才能继承RaisePo
7、stBackEvent事件public void RaisePostBackEvent(string cvcntArgumcnt) ( OnClick(EventArgs. Empty); )protected virtual void OnClick(EventArgs e) ( 〃点击选择日期按钮时,如果日历子控件没有显示那么显示出来并将文本框的值赋值给日 历子控件 if (_Calendar. Attributes[^display*] != (Calendar. SelectedDate = DateTime. Parse(Text): —Calendar. Style. A
8、dd ("display",;) ) 〃复合控件中的日历控件日期变化事件 private void Calendar .SelectionChanged(object sender, EventArgs e)〃中选择的日期变化时,将所选日期赋值给文本框并将日历子控件隐藏 Text = _Calcndar. SclcctedDatc. ToStringO ;_Calendar. Style. Add("display","none"); ) } } 在上面的代码中,需要注意以下几点: • 如果你想将此控件的某些属性供重载,那么在声明属性前加上virtual关键字; • 在页面输
9、出此控件时(即在Render事件中),是先定义子控件的样式或属性, 然后再产生子控件; • 在隐藏日历子控件时,建议不要使用Visible属性来显示/隐藏,使用 Visible=false隐藏时服务器端将不会将口历控件HTML代码发送给客户端,会导致复合 控件装载日历控件的表格会空白一块出来,影响页面的布局。所以使用样式 display:none设置来使日历控件在客户端隐藏,但是HTML代码依然存在于页面中; B CK) 48Px Mh 136PM □注第 (DdtaBndir^) □ 外, BdckCotor BxderCdcr B
10、ordet ** Border MMth ftXtorGtyte BORD€R RIGHT: gray IpM soM; B ButtonText Ma D^eFcrm^ lonjpMeTwne Q Ry* ForeCdor □ Text 200S-12-01 日行为 AccessKey EnaUed True En4deV5ev6tate True Tabindex 0 ToolTp VHit4e True 日奈厚 DatrPKkrrl 偿性
11、三 DatePKketl AQjdCatenda MtePHw 瓦%回刃H Text 设置该日m按丽b・ 3 WrbForml - Microsoft Internet Explorer 文件© 物睚)S9W 4URCA) XJKD 帮助(mf J 8后退・• • © @ GI ◎披案力收♦夹 地址(Q),Imcdhost/TestWob/TosKontrd.ospx T ~转到 播接“ [2005-12-2 2005年 12月 星明日星期一星期二星u三星m四 星期五星期六 9成及致 叁152222 zll212a 叁心阳2Z 5121281 4111825 福
12、完毕 就本地intranet K*决方寞资>»?告整器野屋性 四、结束语 在编写服务器控件时,需要一定的HTML语言基础,也要清楚.NET程序的请求处理 方式。服务器控件封装了客户端行为及逻辑判断,无需开发者添加更多代码。当然,有 些地方使用服务器控件可以带来方便,但是也增加了服务器的负荷。有时适当的结合JavaScript使一些代码在客户端运行,可提高WEB应用程序效率。 附录资料: 不需要的可以自行删除Abstract: Based on the comprehensive analysis on the plastic part's structure service re
13、quirement, mounding quality and mould menu factoring cost. A corresponding injection mould of internal side core pulling was designed. By adopting the multi-direction and multi-combination core-pulling. A corresponding injection mould of internal side core pulling was designed, the working process o
14、f the mould was introduced C语言详解-枚举类型注:以下全部代码的执行环境为VC++6.0 在程序中,可能需要为某些整数定义一个别名,我们可以利用预处理指令#define来完成这 项工作,您的代码可能是: #define MON Idcfine TUE 2 # define WED 3define THU 4 # define FRI 5define SAT 6 # dcfinc SUN 7在此,我们定义一种新的数据类型,希望它能完成同样的工作。这种新的数据类型叫枚举型。 1 .定义一种新的数据类型-枚举型 以下代码定义了这种新的数据类型-枚举型cnum
15、 DAY { MON=1,TUE, WED, THU, FRI, SAT, SUN}; (1)枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号, 隔开。 ⑵DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。 (3)第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加I。 (4)可以人为设定枚举成员的值,从而自定义某个范围内的整数。 (5)枚举型是预处理指令#define的替代。 (6)类型定义以分号;结束。 2 .使用枚举类型对变量进行声明新的数据类型定义完成后,它就可以使用了。我们已经见过最基本的数据类型
16、如:整型ini, 单精度浮点型float,双精度浮点型double,字符型char,短整型short等等。用这些基本数据 类型声明变量通常是这样: char char int a; 〃变量a的类型均为字符型char letter;y, z; 〃变量x,y和z的类型均为整型int int number;double m, n; double result; 〃变显result的类型为双精度浮点型double 既然枚举也是一种数据类型,那么它和基本数据类型一样也可以对变量进行声明。 方法一:枚举类型的定义和变量的声明分开enuni DAY { MON=1,TUE, WED, THU,
17、 FRI, SAT, SUN1; enuni DAY yesterday;enum DAY today; enum DAY tomorrow; 〃变a tomorrow 的类型为枚举型 enum DAYenum DAY good_day, bad_day; //变量 good_day 和 bad_day 的类型均为枚举型 enum DAY 方法二:类型定义与变量声明同时进行: enum〃跟第一个定义不同的是,此处的标号DAY省略,这是允许的。 {Saturday, sunday = 0, monday, tuesday, Wednesday, thursday, friday } wo
18、rkday; 〃变量workday的类型为枚举型enum DAYenuni week { Mon=l, Tue, Wed, Thu, Fri Sat, Sun} days; 〃变量 days 的类型为枚举型 enum week enum BOOLEAN { false, true } end_flag, match_flag; 〃定义枚举类型并声明了两个枚举型变 量方法三:用typedef关键字将枚举类型定义成别名,并利用该别名进行变量声明: typedef enum workday ( Saturday, sunday = 0, monday, tuesday, Wednesday, t
19、hursday, friday} workday; 〃此处的workday为枚举型enum workday的别名 workday today, tomorrow; 〃变量 today 和 tomorrow 的类型为枚举型 workday,也即 enum workday enum workday 中的 workday 可以省略: (ypedef enum {Saturday, sunday = 0, monday, tuesday, Wednesday, ihursday, friday } workday; 〃此处的workday为枚举型enum workday的别名workday to
20、day, tomorrow; 〃变量 loday 和 tomorrow 的类型为枚举型 workday,也即 enum workday 也可以用这种方式: typedef enum workday { Saturday, sunday = 0, monday, tuesday, Wednesday, thursday, friday );workday today, tomorrow; 〃变量 today 和 tomorrow 的类型为枚举型 workday,也即 enum workday 注意:同一个程序中不能定义同名的枚举类型,不同的枚举类型中也不能存在同名的命名常 量。错误例如如
21、下所示: 错误声明•:存在同名的枚举类型typedef enum { Wednesday, thursday, friday } workday;typedef enum WEEK Saturday, sunday = 0, monday, } workday;错误声明二:存在同名的枚举成员 typcdcf cnum ( Wednesday, thursday, friday } workday」;typcdcf enum WEEK { Wednesday, sunday = 0, monday, } workday_2;.使用枚举类型的变量 2.1 对枚举型的变量赋值。 实
22、例将枚举类型的赋值与基本数据类型的赋值进行了比照:
方法一:先声明变量,再对变量赋值#include
23、row = WED:
printf("%d %d %d \n", yesterday, today, tomorrow);方法二:声明变量的同时赋初值
/include
24、D;
printf("%d %d %d \n", yesterday, today, tomorrow);I
方法三:定义类型的同时声明变量,然后对变量赋值。
#include
25、z = 30;
/*对枚举型的变量赋值*/
yesterday = MON;
today = TUE;
tomorrow = WED;
printf("%d %d %d \n", x, y, z); 〃输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); 〃输出:12 3)
方法四:类型定义,变量声明,赋初值同时进行。
#include
26、FRI,
SAT,
SUN}
yesterday = MON, today = TUE, tomorrow = WED;/*定义三个具有基本数据类型的变量,并赋初值。它们都为全局变量*/
inlx= 10,y = 2O,z = 3O;void main()
{
printf("%d %d %d \n", x, y, z); 〃输出:10 20 30
printf("%d %d %d \n", yesterday, today, tomorrow); 〃输出:12 31
2.2 对枚举型的变量赋整数值时,需要进行类型转换。
#include
27、{ MON=1,TUE, WED, THU, FRI, SAT, SUN };
void main()
enum DAY yesterday, today, tomorrow;
yesterday = TUE;
today = (enum DAY) (yesterday + 1); 〃类型转换
tomorrow = (enuni DAY) 30; 〃类型转换
//tomorrow = 3; 〃错误
printf("%d %d %d \n", yesterday, today, tomorrow); 〃输出:2 3 30 )使用枚举型变量
#include
28、m { BELL='\a; BACKSPACE = '\b', HTAB=W RETURN=V, NEWLINE= \n\ VTAB= W, SPACE= *'I; enum BOOLEAN { FALSE = 0, TRUE } match_flag;void main() { int index = 0; int count_oUetter = 0; int count_ofLspace = 0; char str[] = "I'm Ely efod"; match_flag = FALSE; for(; str[index] != *\0'; index+
29、)if( SPACE != str[index]) count_of_lctter++;else {match_nag = (enum BOOLEAN) 1; count_oLspace++; 服务器控件在设计时以runal二" server”脚本代码嵌入到aspx文件中来表示此控 件是在服务器端运行的。在服务器控件所在页面提交回传(PostBack)过程中是依靠 ViewState (视图状态)来维护控件状态的。所以我们在设计服务器控件属性时,其值 应保存在ViewState中。 三、代码编写 C#中有一个日历控件Calendar,但是现在我需要一个可以下拉的日历控件,并且初
30、始时不显示日历,当我点击下拉按钮时才弹出,并且中选择了日期,日历会自动隐藏且 选择的日期值会显示到相应的输入框中。显然Calendar控件不能满足我的需要,但是 稍后我会在我的自定义控件中用到它。 首先新建工程,在工程类型中选择Visual C#工程,在模板列表中选择Web控件库, 输入工程名称AquaCalendar,然后选择工程所在目录,点击【确定】按钮。C#将会生成 基本的框架代码。将工程中的类文件和类名改名为DatePicker (即日期控件的类名)。 由于DatePicker是可视化控件,所以我们必须从System. Web. UI. WebControls继承。 并且它包括一个输
31、入框,一个按钮和日历控件,需要在DatePicker类中声明它们。像 这种以多个服务器控件组合的控件成为复合控件。代码如下,比拟重要的方法和代码在 注释中会加以说明: using System; using System. Web. UI; using System. Web. UI. WebControls; using System. ComponentModel; using System. Drawing; namespace AquaCalendar [DefaultProperty("Text"), 〃在属性工具箱中显示的默认屈性 ToolboxData("<{0}
32、DatePicker runat=server>{0}:DatePicker>*)] public class DatePicker : System. Web. UI. WebControls. WebControl , IPostBackEventHandler printf("%s %d times %c", match_flag ? "match": "not match", count_of_space, NEWLINE); printf("coiint of letters: %d %c%c", count_of_letter. NEWLINE. RETURN);} 输出
33、 match 2 times count of letters: 10 Press any key to continue
3 .枚举类型与sizeof运算符#include
34、cnum escapes)); //4 bytes printf("%d bytes \n", sizeof(escapes)); //4 bytes prinlf("%d bytes \n*\ sizeof(enum BOOLEAN)); //4 bytes printf("%d bytes \n", sizeof(BOOLEAN)); //4 bytes printf("%d bytes \n", sizeof(match_flag)); //4 bytes printf("%d bytes \n", sizcof(SPACE)); //4 bytes printf("%d b
35、ytes \n", sizeof(NEWLINE)); //4 bytes
printf("%d bytes \n", sizeof(FALSE)); //4 bytes
printf("%d bytes \n*\ sizeof(0)); //4 bytes I 5.综合举例 #include
36、d main() { /* Season */ printf("%d \n", spring); // 0 printf("%d, %c \nH, summer, summer); // I (X), d printf("%d \n", fall+winter); // 193 Season mySeason=winter; if(wi ntcr==myScason)printf("mySeason is winter \n"); // mySeason is winter int x=100; if(x==summer)prinlf("x is equal to summe
37、r\n"); // x is equal to summer printf("%d bytes\n", sizcof(spring)); // 4 bytes /* Weekday */ printfC^izeof Weekday is: %d \n", sizeof(Weekday)); //sizeof Weekday is: 4 Weekday today = Saturday; Weekday tomorrow;if( today == Monday) tomorrow = Tuesday; else tomorrow = (Weekday) (today + I); /
38、/remember to convert from int to Weekday }本文来自CSDN--xiaobai32966博客 〃选择日期按钮的默认样式 private const string _BUTTONDEFAULTSTYLE = "BORDER-RIGHT: gray Ipx solid;BORDER-TOP: gray Ipx solid; BORDER-LEFT: gray Ipx solid; CURSOR: hand; BORDER-BOTTOM: gray Ipx solid;"; 〃按钮默认文本private const string BLTTONDEFAUL
39、TTEXT = private System. Web. UI. WcbControls. Calendar .Calendar;public override ControlCollection Controls ( get ( EnsureChildControlsO ; //确认子控件集都已被创立 return base. Controls; ) ) 〃创立子控件(服务器日历控件)protected override void CreateChiIdControlsO ( Controls. Clear ();.Calendar = new Calendar(); _Cale
40、ndar. ID = MyCalendarlD;_Calendar. SelectedDale = DaleTime. Parse (Text); _Calendar. TitleFormat = TitleFormat. MonthYear;Calendar. NextPrevFormat = NextPrevFormat. ShortMonth; _Calendar. CellSpacing = 0;Calendar. Font. Size = FontUnit. Parse(*9pt*); _Calendar. Font. Name = "Verdana”;_Calendar. S
41、electedDayStyle. BackColor = ColorTranslator. FromHtnil ("#333399"); Calendar. SelectedDayStyle. ForeColor = ColorTranslator. FromHtml("White");—Calendar. DayStyle. BackColor - ColorTranslator. FromHtml("#CCCCCC"); Calendar. TodayDayStyle. BackColor = ColorTranslator. FromHtml(*#999999*);—Calendar
42、 TodayDayStyle. ForcColor = ColorTranslator. FromHtml (*Aqua,z); Calendar. DayHeaderStyle. Font. Size = FontUnit. Parse(w8ptw);_Calendar. DayHeaderStyle. Font. Bold = true: _Calendar. DayHeaderStyle.Height = Unit. Parse(*8pt*);.Calendar. DayHeaderStyle. ForeColor = ColorTranslator. FromHlml("#333
43、333"); _Calendar. NextPrevStyle. Font. Size = FontUnit. Parse("8pt");Calendar. NextPrevStyle. Font. Bold = true; .Calendar. NextPrevStyle. ForeColor = ColorTranslator. FromHtml("White");Calendar. TitleStyle. Font. Size = FontUnit. Parse(“12pt"); _Calcndar. TitlcStylc. Font. Bold = true;_Calendar.
44、TitleStyle. Height = Unit. Parse(*12pt*); Calendar. TitleStyle. ForeColor = ColorTranslator. FromHtml(*White*);_Calendar. TitleStyle. BackColor = ColorTranslator. EromUtml("#333399"); Calendar. 01herMonthDaySty1e. ForeCo1or = ColorTranslator. FromHtml("#999999");_Calendar. NextPrevFormat = NextPre
45、vFormat. CustomText: Calendar. NextMonthText ="下月"; .Calendar. PrevMonthText ="上月"; .Calendar. Style. Add("display", "none"); 〃默认不显示下拉口历控件 .Calendar. SeieelionChanged += new EventHand1 er(_Ca1endar_Se1ectionChanged); this. Controls. Add(.Calendar): ) [ Category (^Appearance"), 〃该属性所属类别,参见图 De
46、faultValue 〃屈性默认值 Description("设置该日期控件的值,〃属性的描述 ] public string Text (get ( EnsureChildControlsO : return (VicwStatcE'Text"]== null)?System. Dat eTime. Today. ToStringt^yyyy-MM-dd*): ViewS tatet^ext^]. ToStringO : } set (EnsureChildControlsO ; DateTime dt = System. DateTime. Today; try (dt =
47、DateTime. Parse(value); ) catch { throw new ArgumentOutOfRangeException(”请输入日期型字符串(例如: 1981-04-29) !");} ViewState[*Text*] = DateFormat == CalendarEnum. LongDateTime?dt. ToString("yyyy-VM-dd"):dt. ToString("yyyy-M-d"); )〃重载服务器控件的Enabled属性,将选择口期按钮变灰(禁用) public override bool Enabled ( get ( Ens
48、urcChildControlsO ; return ViewState[*Enabled*] == null?true:(bool)ViewState["Enabled"]; } set ( EnsureChildControlsO ; ViewState["Enabled”〕 = value; } )public string ButtonStyle ( get ( EnsureChildControlsO ; object o = ViewState[*ButtonSytle/,]; return (o == null)?_BUTTONDEFAULTSTYLE:o. To
49、StringO ; } set ( EnsureCh i1dControls(); ViewState[*ButtonSytle*] = value; ) ) [ DefaultValue(CalendarEnum. LongDateTime), ]public CalendarEnum DateFormat ( get EnsureCh i1dControls();object format = ViewState[*DateFormatw]; return format =- null?CalendarEnum. LongDateTime:(CalendarEnum)forma
50、t;) set ( EnsureChi IdControlsO ;ViewState[*DateFormatw] = value; DateTime dt = DateTime. Parse(Text);Text=DateFormat == CalendarEnum. LongDateTime?dt. ToString(z,yyyy-MM-(ldw) :dt. ToStringCyyyy-M-dw);) ) [ Browsab1e(fa1se), DesignerSerializationVisibility(DesignerSerializationVisibility. Hi






