翻译|其它|编辑:郝浩|2007-08-21 09:33:18.000|阅读 951 次
概述:
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
一、序言
Visual C#.NET 是微软公司出品的一种新的编程语言(以下简称 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 代码段,当然它也包括后台代码(Code -behind),后缀名是 ascx。所以在开发一些公用的静态页面时(例如页头,页脚)经常用到,但它的缺点是不易继承,不易分发,无法编译成二进制代码来进行部署。但是自定义控件的功能就强大许多,它可以被编译成二进制代码(DLL 文件),可以被扩展、继承、分发。就像 Web Form Control 一样,其实它们每个控件就是一个 DLL 文件。
开发用户控件比较简单,就像编写一个 aspx 页面一样,在这里就不介绍了。本文对象是自定义控件。服务器控件的基类是 System.Web.UI.Control。如果要开发可视化的服务器控件,那我们需要从 System.Web.UI.WebControls 来继承,否则从 System.Web.UI.Control 继承。
服务器控件在设计时以 runat=”server”脚本代码嵌入到 aspx 文件中来表示此控件是在服务器端运行的。在服务器控件所在页面提交回传(PostBack)过程中是依靠 ViewState(视图状态)来维护控件状态的。所以我们在设计服务器控件属性时,其值应保存在 ViewState 中。
三、代码编写
C# 中有一个日历控件 Calendar,但是现在我需要一个可以下拉的日历控件,并且初始时不显示日历,当我点击下拉按钮时才弹出,并且当选择了日期,日历会自动隐藏且选择的日期值会显示到相应的输入框中。显然 Calendar 控件不能满足我的需要,但是稍后我会在我的自定义控件中用到它。
首先新建项目,在项目类型中选择 Visual C# 项目,在模板列表中选择 Web 控件库,输入项目名称 AquaCalendar,然后选择项目所在目录,点击【确定】按钮。C#将会生成基本的框架代码。将项目中的类文件和类名改名为 DatePicker(即日期控件的类名)。由于 DatePicker 是可视化控件,所以我们必须从 System.Web.UI.WebControls 继承。并且它包括一个输入框,一个按钮和日历控件,需要在 DatePicker 类中声明它们。像这种以多个服务器控件组合的控件成为复合控件。代码如下,比较重要的方法和代码在注释中会加以说明:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;
namespace AquaCalendar
{
[DefaultProperty("Text"), //在属性工具箱中显示的默认属性
ToolboxData("<{0}:DatePicker runat=server></{0}:DatePicker>")]
public class DatePicker : System.Web.UI.WebControls.WebControl ,
IPostBackEventHandler
{
//选择日期按钮的默认样式
private const string _BUTTONDEFAULTSTYLE = "BORDER-RIGHT: gray 1px solid;
BORDER-TOP: gray 1px solid; BORDER-LEFT: gray 1px solid; CURSOR: hand;
BORDER-BOTTOM: gray 1px solid;";
//按钮默认文本
private const string _BUTTONDEFAULTTEXT = "...";
private System.Web.UI.WebControls.Calendar _Calendar;
public override ControlCollection Controls
{
get
{
EnsureChildControls(); //确认子控件集都已被创建
return base.Controls;
}
}
//创建子控件(服务器日历控件)
protected override void CreateChildControls()
{
Controls.Clear();
_Calendar = new Calendar();
_Calendar.ID = MyCalendarID;
_Calendar.SelectedDate = DateTime.Parse(Text);
_Calendar.TitleFormat = TitleFormat.MonthYear;
_Calendar.NextPrevFormat = NextPrevFormat.ShortMonth;
_Calendar.CellSpacing = 0;
_Calendar.Font.Size = FontUnit.Parse("
_Calendar.Font.Name = "Verdana";
_Calendar.SelectedDayStyle.BackColor = ColorTranslator.FromHtml("#333399");
_Calendar.SelectedDayStyle.ForeColor = ColorTranslator.FromHtml("White");
_Calendar.DayStyle.BackColor = ColorTranslator.FromHtml("#CCCCCC");
_Calendar.TodayDayStyle.BackColor = ColorTranslator.FromHtml("#999999");
_Calendar.TodayDayStyle.ForeColor = ColorTranslator.FromHtml("Aqua");
_Calendar.DayHeaderStyle.Font.Size = FontUnit.Parse("
_Calendar.DayHeaderStyle.Font.Bold = true;
_Calendar.DayHeaderStyle.Height = Unit.Parse("
_Calendar.DayHeaderStyle.ForeColor = ColorTranslator.FromHtml("#333333");
_Calendar.NextPrevStyle.Font.Size = FontUnit.Parse("
_Calendar.NextPrevStyle.Font.Bold = true;
_Calendar.NextPrevStyle.ForeColor = ColorTranslator.FromHtml("White");
_Calendar.TitleStyle.Font.Size = FontUnit.Parse("
_Calendar.TitleStyle.Font.Bold = true;
_Calendar.TitleStyle.Height = Unit.Parse("
_Calendar.TitleStyle.ForeColor = ColorTranslator.FromHtml("White");
_Calendar.TitleStyle.BackColor = ColorTranslator.FromHtml("#333399");
_Calendar.OtherMonthDayStyle.ForeColor = ColorTranslator.FromHtml("#999999");
_Calendar.NextPrevFormat = NextPrevFormat.CustomText;
_Calendar.NextMonthText = "下月";
_Calendar.PrevMonthText = "上月";
_Calendar.Style.Add("display","none"); //默认不显示下拉日历控件
_Calendar.SelectionChanged += new EventHandler(_Calendar_SelectionChanged);
this.Controls.Add(_Calendar);
}
[
Category("Appearance"), //该属性所属类别,参见图
DefaultValue(""), //属性默认值
Description("设置该日期控件的值。") //属性的描述
]
public string Text
{
get
{
EnsureChildControls();
return (ViewState["Text"] ==
null)?System.DateTime.Today.ToString("yyyy-MM-dd"):ViewState["Text"].ToString();
}
set
{
EnsureChildControls();
DateTime dt = System.DateTime.Today;
try
{
dt = DateTime.Parse(value);
}
catch
{
throw new ArgumentOutOfRangeException("请输入日期型字符串(例如:
}
ViewState["Text"] = DateFormat ==
CalendarEnum.LongDateTime?dt.ToString("yyyy-MM-dd"):dt.ToString("yyyy-M-d");
}
}
//重载服务器控件的 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:o.ToString();
}
set
{
EnsureChildControls();
ViewState["ButtonSytle"] = value;
}
}
[
DefaultValue(CalendarEnum.LongDateTime),
]
public CalendarEnum DateFormat
{
get
{
EnsureChildControls();
object format = ViewState["DateFormat"];
return format == null?CalendarEnum.LongDateTime:(CalendarEnum)format;
}
set
{
EnsureChildControls();
ViewState["DateFormat"] = value;
DateTime dt = DateTime.Parse(Text);
Text=DateFormat ==
CalendarEnum.LongDateTime?dt.ToString("yyyy-MM-dd"):dt.ToString("yyyy-M-d");
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string MyCalendarID //复合控件 ID
{
get
{
EnsureChildControls();
return this.ClientID+"_MyCalendar";
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string MyCalendarName //复合控件名称
{
get
{
EnsureChildControls();
return this.UniqueID+":MyCalendar";
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string DatePickerInputID //复合控件中输入框的 ID
{
get
{
EnsureChildControls();
return this.ClientID+"_DateInput";
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string DatePickerInputName //复合控件中输入框的名称
{
get
{
EnsureChildControls();
return this.UniqueID+":DateInput";
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string DatePickerButtonID //复合控件中按钮的 ID
{
get
{
EnsureChildControls();
return this.ClientID+"_DateButton";
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string DatePickerButtonName //复合控件中按钮的名称
{
get
{
EnsureChildControls();
return this.UniqueID+":DateButton";
}
}
public string ButtonText
{
get
{
EnsureChildControls();
return ViewState["ButtonText"] ==
null?_BUTTONDEFAULTTEXT:(string)ViewState["ButtonText"];
}
set
{
EnsureChildControls();
ViewState["ButtonText"] = value;
}
}
/// <summary>
/// 将此控件呈现给指定的输出参数。
/// </summary>
/// <param name="output"> 要写出到的 HTML 编写器 </param>
protected override void Render(HtmlTextWriter output)
{
//在页面中输出控件时,产生一个表格(二行二列),以下是表格的样式
output.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");
output.AddAttribute(HtmlTextWriterAttribute.Border, "0");
output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");
output.AddStyleAttribute("LEFT", this.Style["LEFT"]);
output.AddStyleAttribute("TOP", this.Style["TOP"]);
output.AddStyleAttribute("POSITION", "absolute");
if (Width != Unit.Empty)
{
output.AddStyleAttribute(HtmlTextWriterStyle.Width, Width.ToString());
}
else
{
output.AddStyleAttribute(HtmlTextWriterStyle.Width, "200px");
}
output.RenderBeginTag(HtmlTextWriterTag.Table); //输出表格
output.RenderBeginTag(HtmlTextWriterTag.Tr); //表格第一行
output.AddAttribute(HtmlTextWriterAttribute.Width, "90%");
output.RenderBeginTag(HtmlTextWriterTag.Td);
//以下是第一行第一列中文本框的属性及其样式设置
if (!Enabled)
{
output.AddAttribute(HtmlTextWriterAttribute.ReadOnly, "true");
}
output.AddAttribute(HtmlTextWriterAttribute.Type, "Text");
output.AddAttribute(HtmlTextWriterAttribute.Id, DatePickerInputID);
output.AddAttribute(HtmlTextWriterAttribute.Name, DatePickerInputName);
output.AddAttribute(HtmlTextWriterAttribute.Value, Text);
output.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
output.AddStyleAttribute(HtmlTextWriterStyle.Height, "100%");
output.AddStyleAttribute(HtmlTextWriterStyle.FontFamily, Font.Name);
output.AddStyleAttribute(HtmlTextWriterStyle.FontSize, Font.Size.ToString());
output.AddStyleAttribute(HtmlTextWriterStyle.FontWeight, Font.Bold?"bold":"");
output.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor,
ColorTranslator.ToHtml(BackColor));
output.AddStyleAttribute(HtmlTextWriterStyle.Color,
ColorTranslator.ToHtml(ForeColor));
output.RenderBeginTag(HtmlTextWriterTag.Input); //输出文本框
output.RenderEndTag();
output.RenderEndTag();
output.AddAttribute(HtmlTextWriterAttribute.Width, "*");
output.RenderBeginTag(HtmlTextWriterTag.Td);
//以下是第一行第二列中按钮的属性及其样式设置
if (!Enabled)
{
output.AddAttribute(HtmlTextWriterAttribute.Disabled, "true");
}
output.AddAttribute(HtmlTextWriterAttribute.Type, "Submit");
output.AddAttribute(HtmlTextWriterAttribute.Id, DatePickerButtonID);
output.AddAttribute(HtmlTextWriterAttribute.Name, DatePickerButtonName);
output.AddAttribute(HtmlTextWriterAttribute.Value, ButtonText);
output.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
output.AddAttribute(HtmlTextWriterAttribute.Onclick,
Page.GetPostBackEventReference(this)); //点击按钮时需要回传服务器来触发后面的 OnClick 事件
output.AddAttribute(HtmlTextWriterAttribute.Style, ButtonStyle);
output.RenderBeginTag(HtmlTextWriterTag.Input); //输出按钮
output.RenderEndTag();
output.RenderEndTag();
output.RenderEndTag();
output.RenderBeginTag(HtmlTextWriterTag.Tr);
output.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");
output.RenderBeginTag(HtmlTextWriterTag.Td);
_Calendar.RenderControl(output); //将日历子控件输出
output.RenderEndTag();
output.RenderEndTag();
output.RenderEndTag();
}
//复合控件必须继承 IpostBackEventHandler 接口,才能继承 RaisePostBackEvent 事件
public void RaisePostBackEvent(string eventArgument)
{
OnClick(EventArgs.Empty);
}
protected virtual void OnClick(EventArgs e)
{
//点击选择日期按钮时,如果日历子控件没有显示则显示出来并将文本框的值赋值给日历子控件
if (_Calendar.Attributes["display"] != "")
{
_Calendar.SelectedDate = DateTime.Parse(Text);
_Calendar.Style.Add("display","");
}
}
//复合控件中的日历控件日期变化事件
private void _Calendar_SelectionChanged(object sender, EventArgs e)
{
//当选择的日期变化时,将所选日期赋值给文本框并将日历子控件隐藏
Text = _Calendar.SelectedDate.ToString();
_Calendar.Style.Add("display","none");
}
}
}
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com