三、代碼編寫
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>")]
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("9pt");
_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("8pt");
_Calendar.DayHeaderStyle.Font.Bold = true;
_Calendar.DayHeaderStyle.Height = Unit.Parse("8pt");
_Calendar.DayHeaderStyle.ForeColor = ColorTranslator.FromHtml("#333333");
_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");
_Calendar.TitleStyle.Font.Bold = true;
_Calendar.TitleStyle.Height = Unit.Parse("12pt");
_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("請輸入日期型字符串(例如:1981-04-29)!");
}
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;
}
}
///
/// 將此控件呈現給指定的輸出參數。
///
/// 要寫出到的 Html 編寫器
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");
}
}
}