服务器

位置:IT落伍者 >> 服务器 >> 浏览文章

用C#.NET编写服务器日期控件


发布日期:2019年08月08日
 
用C#.NET编写服务器日期控件

序言

Visual 是微软公司出品的一种新的编程语言(以下简称C#)它继承了C语言的一些特性也加入了一些新的元素以前用过Delphi开发程序的人可能刚开始使用C#的时候对其有一种似曾相识的感觉(至少包括我)是的C#语言的创始人正是以前在Borland公司开发出Delphi语言的Anders Hejlsberg在我开始使用C#开发程序时就觉得它是一款很棒的开发Windows Form & Web程序的RAD工具

在开发Web程序方面C#的出现打破了以前的网页开发模式实现了与开发Windows

Form程序一样的所见即所得的功能C#提供了一些常用的Web Form Control供开发人员使用并且只需将控件拖入页面中即可非常简单但有时这些控件也不能满足开发人员的需要需要开发人员自己编写用户控件(User Control)或自定义控件(Custom Control)来满足需求在这里我将讲解如何在C#中开发服务器控件

预备知识

在C#中可以开发两种服务器控件一个是用户控件(User Control)和自定义控件(Custom Control)用户控件的本质与页面文件(ASPx文件)差不多是可被其它aspx页面重复使用的HTML代码段当然它也包括后台代码(Codebehind)后缀名是ascx所以在开发一些公用的静态页面时(例如页头页脚)经常用到但它的缺点是不易继承不易分发无法编译成二进制代码来进行部署但是自定义控件的功能就强大许多它可以被编译成二进制代码(DLL文件)可以被扩展继承分发就像Web Form Control一样其实它们每个控件就是一个DLL文件

开发用户控件比较简单就像编写一个aspx页面一样在这里就不介绍了本文对象是自定义控件服务器控件的基类是SystemWebUIControl如果要开发可视化的服务器控件那我们需要从SystemWebUIWebControls来继承否则从SystemWebUIControl继承

服务器控件在设计时以runat=server脚本代码嵌入到aspx文件中来表示此控件是在服务器端运行的在服务器控件所在页面提交回传(PostBack)过程中是依靠ViewState(视图状态)来维护控件状态的所以我们在设计服务器控件属性时其值应保存在ViewState中

代码编写

C#中有一个日历控件Calendar但是现在我需要一个可以下拉的日历控件并且初始时不显示日历当我点击下拉按钮时才弹出并且当选择了日期日历会自动隐藏且选择的日期值会显示到相应的输入框中显然Calendar控件不能满足我的需要但是稍后我会在我的自定义控件中用到它

首先新建项目在项目类型中选择Visual C#项目在模板列表中选择Web控件库输入项目名称AquaCalendar然后选择项目所在目录点击【确定】按钮C#将会生成基本的框架代码将项目中的类文件和类名改名为DatePicker(即日期控件的类名)由于DatePicker是可视化控件所以我们必须从SystemWebUIWebControls继承并且它包括一个输入框一个按钮和日历控件需要在DatePicker类中声明它们像这种以多个服务器控件组合的控件成为复合控件代码如下比较重要的方法和代码在注释中会加以说明

using System;

using SystemWebUI;

using SystemWebUIWebControls;

using SystemComponentModel;

using SystemDrawing;

namespace AquaCalendar

{

[DefaultProperty(Text)

//在属性工具箱中显示的默认属性

ToolboxData(<{}:DatePicker runat=server>)]

public class DatePicker :

SystemWebUIWebControlsWebControl

IPostBackEventHandler

{

//选择日期按钮的默认样式

private const string _BUTTONDEFAULTSTYLE = BORDERRIGHT: gray px solid; BORDERTOP: gray px solid; BORDERLEFT: gray px solid; CURSOR: hand; BORDERBOTTOM: gray px solid;;

//按钮默认文本

private const string _BUTTONDEFAULTTEXT = ;

private SystemWebUIWebControlsCalendar _Calendar;

public override ControlCollection Controls

{

get

{

EnsureChildControls(); //确认子控件集都已被创建

return baseControls;

}

}

//创建子控件(服务器日历控件)

protected override void CreateChildControls()

{

ControlsClear();

_Calendar = new Calendar();

_CalendarID = MyCalendarID;

_CalendarSelectedDate = DateTimeParse(Text);

_CalendarTitleFormat = TitleFormatMonthYear;

_CalendarNextPrevFormat = NextPrevFormatShortMonth;

_CalendarCellSpacing = ;

_CalendarFontSize = FontUnitParse(pt);

_CalendarFontName = Verdana;

_CalendarSelectedDayStyleBackColor = ColorTranslatorFromHtml(#);

_CalendarSelectedDayStyleForeColor = ColorTranslatorFromHtml(White);

_CalendarDayStyleBackColor = ColorTranslatorFromHtml(#CCCCCC);

_CalendarTodayDayStyleBackColor = ColorTranslatorFromHtml(#);

_CalendarTodayDayStyleForeColor = ColorTranslatorFromHtml(Aqua);

_CalendarDayHeaderStyleFontSize = FontUnitParse(pt);

_CalendarDayHeaderStyleFontBold = true;

_CalendarDayHeaderStyleHeight = UnitParse(pt);

_CalendarDayHeaderStyleForeColor = ColorTranslatorFromHtml(#);

_CalendarNextPrevStyleFontSize = FontUnitParse(pt);

_CalendarNextPrevStyleFontBold = true;

_CalendarNextPrevStyleForeColor = ColorTranslatorFromHtml(White);

_CalendarTitleStyleFontSize = FontUnitParse(pt);

_CalendarTitleStyleFontBold = true;

_CalendarTitleStyleHeight = UnitParse(pt);

_CalendarTitleStyleForeColor = ColorTranslatorFromHtml(White);

_CalendarTitleStyleBackColor = ColorTranslatorFromHtml(#);

_CalendarOtherMonthDayStyleForeColor = ColorTranslatorFromHtml(#);

_CalendarNextPrevFormat = NextPrevFormatCustomText;

_CalendarNextMonthText = 下月;

_CalendarPrevMonthText = 上月;

_CalendarStyleAdd(displaynone); //默认不显示下拉日历控件

_CalendarSelectionChanged += new EventHandler(_Calendar_SelectionChanged);

thisControlsAdd(_Calendar);

}

[

Category(Appearance) //该属性所属类别参见图

DefaultValue() //属性默认值

Description(设置该日期控件的值) //属性的描述

]

public string Text

{

get

{

EnsureChildControls();

return (ViewState[Text] == null)?SystemDateTimeTodayToString(yyyyMMdd):ViewState[Text]ToString();

}

set

{

EnsureChildControls();

DateTime dt = SystemDateTimeToday;

try

{

dt = DateTimeParse(value);

}

catch

{

throw new ArgumentOutOfRangeException(请输入日期型字符串(例如)!);

}

ViewState[Text] = DateFormat == CalendarEnumLongDateTime?dtToString(yyyyMMdd):dtToString(yyyyMd);

}

}

//重载服务器控件的Enabled属性将选择日期按钮变灰(禁用)

public override bool Enabled

{

get

{

EnsureChildControls();

return ViewState[Enabled] == null?true:(bool)ViewState[Enabled];

}

set

{

EnsureChildControls();

ViewState[Enabled] = value;

}

}

public string ButtonStyle

{

get

{

EnsureChildControls();

object o = ViewState[ButtonSytle];

return (o == null)?_BUTTONDEFAULTSTYLE:oToString();

}

set

{

EnsureChildControls();

ViewState[ButtonSytle] = value;

}

}

[

DefaultValue(CalendarEnumLongDateTime)

]

public CalendarEnum DateFormat

{

get

{

EnsureChildControls();

object format = ViewState[DateFormat];

return format == null?CalendarEnumLongDateTime:(CalendarEnum)format;

}

set

{

EnsureChildControls();

ViewState[DateFormat] = value;

DateTime dt = DateTimeParse(Text);

Text=DateFormat == CalendarEnumLongDateTime?dtToString(yyyyMMdd):dtToString(yyyyMd);

}

}

[

Browsable(false)

DesignerSerializationVisibility(DesignerSerializationVisibilityHidden)

]

public string MyCalendarID //复合控件ID

{

get

{

EnsureChildControls();

return thisClientID+_MyCalendar;

}

}

[

Browsable(false)

DesignerSerializationVisibility(DesignerSerializationVisibilityHidden)

]

public string MyCalendarName //复合控件名称

{

get

{

EnsureChildControls();

return thisUniqueID+:MyCalendar;

}

}

[

Browsable(false)

DesignerSerializationVisibility(DesignerSerializationVisibilityHidden)

]

public string DatePickerInputID //复合控件中输入框的ID

{

get

{

EnsureChildControls();

return thisClientID+_DateInput;

}

}

[

Browsable(false)

DesignerSerializationVisibility(DesignerSerializationVisibilityHidden)

]

public string DatePickerInputName //复合控件中输入框的名称

{

get

{

EnsureChildControls();

return thisUniqueID+:DateInput;

}

}

[

Browsable(false)

DesignerSerializationVisibility(DesignerSerializationVisibilityHidden)

]

public string DatePickerButtonID //复合控件中按钮的ID

{

get

{

EnsureChildControls();

return thisClientID+_DateButton;

}

}

[

Browsable(false)

DesignerSerializationVisibility(DesignerSerializationVisibilityHidden)

]

public string DatePickerButtonName //复合控件中按钮的名称

{

get

{

EnsureChildControls();

return thisUniqueID+:DateButton;

}

}

public string ButtonText

{

get

{

EnsureChildControls();

return ViewState[ButtonText] == null?_BUTTONDEFAULTTEXT:(string)ViewState[ButtonText];

}

set

{

EnsureChildControls();

ViewState[ButtonText] = value;

}

}

///

/// 将此控件呈现给指定的输出参数

///

///

要写出到的 HTML 编写器

protected override void Render(HtmlTextWriter output)

{

//在页面中输出控件时产生一个表格(二行二列)以下是表格的样式

outputAddAttribute(HtmlTextWriterAttributeCellspacing );

outputAddAttribute(HtmlTextWriterAttributeBorder );

outputAddAttribute(HtmlTextWriterAttributeCellpadding );

outputAddStyleAttribute(LEFT thisStyle[LEFT]);

outputAddStyleAttribute(TOP thisStyle[TOP]);

outputAddStyleAttribute(POSITION absolute);

if (Width != UnitEmpty)

{

outputAddStyleAttribute(HtmlTextWriterStyleWidth WidthToString());

}

else

{

outputAddStyleAttribute(HtmlTextWriterStyleWidth px);

}

outputRenderBeginTag(HtmlTextWriterTagTable); //输出表格

outputRenderBeginTag(HtmlTextWriterTagTr); //表格第一行

outputAddAttribute(HtmlTextWriterAttributeWidth %);

outputRenderBeginTag(HtmlTextWriterTagTd);

//以下是第一行第一列中文本框的属性及其样式设置

if (!Enabled)

{

outputAddAttribute(HtmlTextWriterAttributeReadOnly true);

}

outputAddAttribute(HtmlTextWriterAttributeType Text);

outputAddAttribute(HtmlTextWriterAttributeId DatePickerInputID);

outputAddAttribute(HtmlTextWriterAttributeName DatePickerInputName);

outputAddAttribute(HtmlTextWriterAttributeValue Text);

outputAddStyleAttribute(HtmlTextWriterStyleWidth %);

outputAddStyleAttribute(HtmlTextWriterStyleHeight %);

outputAddStyleAttribute(HtmlTextWriterStyleFontFamily FontName);

outputAddStyleAttribute(HtmlTextWriterStyleFontSize FontSizeToString());

outputAddStyleAttribute(HtmlTextWriterStyleFontWeight FontBold?bold:);

outputAddStyleAttribute(HtmlTextWriterStyleBackgroundColor ColorTranslatorToHtml(BackColor));

outputAddStyleAttribute(HtmlTextWriterStyleColor ColorTranslatorToHtml(ForeColor));

outputRenderBeginTag(HtmlTextWriterTagInput); //输出文本框

outputRenderEndTag();

outputRenderEndTag();

outputAddAttribute(HtmlTextWriterAttributeWidth *);

outputRenderBeginTag(HtmlTextWriterTagTd);

//以下是第一行第二列中按钮的属性及其样式设置

if (!Enabled)

{

outputAddAttribute(HtmlTextWriterAttributeDisabled true);

}

outputAddAttribute(HtmlTextWriterAttributeType Submit);

outputAddAttribute(HtmlTextWriterAttributeId DatePickerButtonID);

outputAddAttribute(HtmlTextWriterAttributeName DatePickerButtonName);

outputAddAttribute(HtmlTextWriterAttributeValue ButtonText);

outputAddStyleAttribute(HtmlTextWriterStyleWidth %);

outputAddAttribute(HtmlTextWriterAttributeOnclick PageGetPostBackEventReference(this)); //点击按钮时需要回传服务器来触发后面的OnClick事件

outputAddAttribute(HtmlTextWriterAttributeStyle ButtonStyle);

outputRenderBeginTag(HtmlTextWriterTagInput); //输出按钮

outputRenderEndTag();

outputRenderEndTag();

outputRenderEndTag();

outputRenderBeginTag(HtmlTextWriterTagTr);

outputAddAttribute(HtmlTextWriterAttributeColspan );

outputRenderBeginTag(HtmlTextWriterTagTd);

_CalendarRenderControl(output); //将日历子控件输出

outputRenderEndTag();

outputRenderEndTag();

outputRenderEndTag();

}

//复合控件必须继承IpostBackEventHandler接口才能继承RaisePostBackEvent事件

public void RaisePostBackEvent(string eventArgument)

{

OnClick(EventArgsEmpty);

}

protected virtual void OnClick(EventArgs e)

{

//点击选择日期按钮时如果日历子控件没有显示则显示出来并将文本框的值赋值给日历子控件

if (_CalendarAttributes[display] != )

{

_CalendarSelectedDate = DateTimeParse(Text);

_CalendarStyleAdd(display);

}

}

//复合控件中的日历控件日期变化事件

private void _Calendar_SelectionChanged(object sender EventArgs e)

{

//当选择的日期变化时将所选日期赋值给文本框并将日历子控件隐藏

Text = _CalendarSelectedDateToString();

_CalendarStyleAdd(displaynone);

}

}

}

在上面的代码中需要注意以下几点

·如果你想将此控件的某些属性供重载则在声明属性前加上virtual关键字

·在页面输出此控件时(即在Render事件中)是先定义子控件的样式或属性然后再产生子控件

·在隐藏日历子控件时建议不要使用Visible属性来显示/隐藏使用Visible=false隐藏时服务器端将不会将日历控件HTML代码发送给客户端会导致复合控件装载日历控件的表格会空白一块出来影响页面的布局所以使用样式display=none设置来使日历控件在客户端隐藏但是HTML代码依然存在于页面中

结束语

在编写服务器控件时需要一定的HTML语言基础也要清楚NET程序的请求处理方式服务器控件封装了客户端行为及逻辑判断无需开发者添加更多代码当然有些地方使用服务器控件可以带来方便但是也增加了服务器的负荷有时适当的结合JavaScript使一些代码在客户端运行可提高WEB应用程序效率

               

上一篇:ASP.NET2.0服务器控件之创建复杂属性

下一篇:HTTP协议的chunked编码