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("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"); } } } |
·如果你想將此控件的某些屬性供重載,則在聲明屬性前加上virtual關鍵字;
·在頁面輸出此控件時(即在Render事件中),是先定義子控件的樣式或屬性,然后再產生子控件;
·在隱藏日歷子控件時,建議不要使用Visible屬性來顯示/隱藏,使用Visible=false隱藏時服務器端將不會將日歷控件HTML代碼發送給客戶端,會導致復合控件裝載日歷控件的表格會空白一塊出來,影響頁面的布局。所以使用樣式display=none設置來使日歷控件在客戶端隱藏,但是HTML代碼依然存在于頁面中;
日歷控件
四、結束語
在編寫服務器控件時,需要一定的HTML語言基礎,也要清楚.NET程序的請求處理方式。服務器控件封裝了客戶端行為及邏輯判斷,無需開發者添加更多代碼。當然,有些地方使用服務器控件可以帶來方便,但是也增加了服務器的負荷。有時適當的結合javascript使一些代碼在客戶端運行,可提高WEB應用程序效率。