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

转载 2007年09月19日 13:14:00

 一、序言

  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>")]
 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应用程序效率

自己制作的一款日期插件

一直在考虑制作一款日期插件,以前一直没时间,也觉得自己肯定完不成这个插件的,最近一段时间事儿不是狠多,就留给了自己足够的时间去开发这一款插件,开发过程中你就会发现其实真的特么的很简单,有些看起来很难很...
  • ccj1990528
  • ccj1990528
  • 2015年04月15日 12:54
  • 1178

WEB页面常用基本控件测试用例

一、树控件的测试外观操作 1)项目中的所有树是否风格一致 2)树结构的默认状态是怎样的。比如默认树是否是展开,是展开几级?  是否有默认的焦点? 默认值是什么?展开的节点图标和颜色?  2、...
  • zmdzbzbhss123
  • zmdzbzbhss123
  • 2016年11月08日 10:48
  • 578

自定义时间日历控件解析

自定义时间日历控件解析 在android开发中我们往往会遇到一些用现有控件难以实现或者实现起来不太容易,且需要重复使用的时候,我们不可能每次都用复杂的代码来实现吧,这样不止浪费了时间,还要付出更多的...
  • qow278770902
  • qow278770902
  • 2016年05月31日 13:10
  • 894

js 常用日期控件使用

一、My97DatePicker当前最新版本: 4.8 官网:http://www.my97.net/ csdn下载地址: http://download.csdn.net/detail/czw...
  • czw2010
  • czw2010
  • 2015年04月11日 22:34
  • 8508

Android显示时间和日期的控件的使用总结

Android显示时间和日期的控件的使用总结 相关类的认识 Picker(DatePicker、TimerPicker、NumberPicker)...
  • wenzhi20102321
  • wenzhi20102321
  • 2016年10月09日 09:07
  • 14582

jquery ui 日期控件中文

jquery.ui.datepicker-zh-CN.js为日期控件国际化中文资源文件 1.设置对应的日期控件相关参数 $( "#startDatepicker" ).datetimepicker({...
  • xiaomin1991222
  • xiaomin1991222
  • 2016年03月10日 16:05
  • 857

JAVA SWING 日期选择控件(目前支持JLable和JTextField)

package com.monitor.date; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.a...
  • LucasXu01
  • LucasXu01
  • 2017年05月06日 16:59
  • 1211

selenium之 时间日期控件的处理

很多人问时间日期的空间怎么处理,但是时间日期控件各种各样,你可能遇到正常点的像这样: 当然也可能遇到难点的,像这样: 当然,也不排除会遇到变态的,像这样: 呵呵,真要一个个想着怎么去选择,简直是...
  • huilan_same
  • huilan_same
  • 2016年08月31日 15:13
  • 8977

(1) 漂亮的日期控件

1 前言 这是一款漂亮,易用的js日期控件 , 可以自定义时间格式 , 定义最大时间,最小时间 , 可以选择年月日,时分秒   点击  下载地址  ,下载js文件 2 使用方法   2...
  • jianfpeng241241
  • jianfpeng241241
  • 2016年02月19日 11:25
  • 470

JS日期选择器(兼容IE,Firefox,Opera等主流浏览器)

JS文件下载:   1. CSDN下载地址: http://download.csdn.net/detail/u013068377/8657779 程序截图: ...
  • u013068377
  • u013068377
  • 2015年05月03日 22:41
  • 1808
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:用VisualC#.NET编写服务器日期控件
举报原因:
原因补充:

(最多只允许输入30个字)