ASP.NET自带的日期控件可能有很多朋友用着觉得不太方便,我们可以自己动手写一个,当然主要 还是JS完成,为了让开发时使用更方便,在此将它封装成自定义控件,效果如图:

关于这个控件有些部分还没有完成,以前写的,现在懒得写了,如果有兴趣的朋友可以改进一下。
步骤:
1)新建一个C#项目,选择自定义控件库。
2) 将SelDate.Cs添加到项目中
3)将其他的.js,.css.gif文件添加到Resource目录中,编辑生成DLL。
4)使用控件,在工具箱的某个选项卡中右键->选择项,选择生成的DLL,这个控件的图标就会出现在工具箱中。如图:

5)将控件拖到页面中
关于控件的使用,提供了几个属性:
CssClass是指那个TextBox的样式
ImageCssClass 图片的样式
ImageUrl图片地址,日历图标的地址,默认可以不用写。
NotNull 是否必填日期。
sDate 当前选中的日期,String型。
sTodayImageUrl 这是当日图标的地址,不填用默认就可。
UseDefaultStyle 是否使用默认样式,如果为False,控件不加载默认css文件,需要用户在页面,链接一个样式表。样式的名称,可参考生成的HTML代码。
以下是我的使用代码:
<%@ Register Assembly="ZFControls" Namespace="ZFControls" TagPrefix="cc1" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>无标题页</title>
<style>
.txt
{
border:solid 1px gray;
font-size:12px;
}
input
{
font-size:12px;
}
td{
font-size:12px;
}
body
{
font-size:12px;
}
</style>
</head>
<body >
<Form id="form1" runat="server">
<cc1:SelDate ID="SelDate1" SelectType="TimeOnly" UseDefaultStyle ="" Cssclass="txt" runat="server" />
<cc1:SelDate ID="SelDate2" Cssclass="txt" runat="server" />
<cc1:SelDate ID="SelDate3" Cssclass="txt" runat="server" />
</Form>
</body>
</html>
<script type="text/javascript">
function getCookie(name)//取cookies函数
{
alert(document.cookie);
var arr = document.cookie.match(new RegExp("(^| )"+name+"=([^;]*)(;|$)"));
if(arr != null) return unescape(arr[2]); return null;
}
</script>
以下是控件源码及资源文件
主程序:SelDate.Cs
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Drawing;
using System.Web.UI.HtmlControls;
namespace ZFControls
{
/// <summary>
/// SelDate 的摘要说明。
/// </summary>
[DefaultProperty("Text"),
ToolboxData("<{0}:SelDate runat=server></{0}:SelDate>"),
ToolboxBitmap(typeof(System.Web.UI.WebControls.Calendar))
]
public class SelDate : System.Web.UI.WebControls.WebControl
{
private TextBox txtInput;
/// <summary>
///
/// </summary>
[Bindable(true),
Category("Appearance"),
DefaultValue("")]
public string sDate
{
get
{
if(CCConvert.IsDateTime(this.txtInput.Text))
{
return this.txtInput.Text;
}else return String.Empty;
}
set
{
if(CCConvert.IsDateTime(value))
{
this.txtInput.Text = value;
}
}
}
/// <summary>
/// 控件右侧图标地址
/// </summary>
[Bindable(true), Category("Appearence"), DefaultValue(""), Editor(typeof(System.Web.UI.Design.ImageUrlEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string ImageUrl
{
get
{
return ViewState["ImageUrl"] != null?(string)ViewState["ImageUrl"]:String.Empty;
}
set
{
ViewState["ImageUrl"] = value;
}
}
/// <summary>
/// 控件右侧图标地址
/// </summary>
public bool NotNull
{
get
{
return ViewState["NotNull"] != null?(bool)ViewState["NotNull"]:false;
}
set
{
ViewState["NotNull"] = value;
}
}
/// <summary>
/// 控件右侧图标地址
/// </summary>
public string ImageCssClass
{
get
{
return ViewState["ImageCssClass"] != null?(string)ViewState["ImageCssClass"]:"calimg";
}
set
{
ViewState["ImageCssClass"] = value;
}
}
/// <summary>
/// 控件右侧图标地址
/// </summary>
public SelectDateType SelectType
{
get
{
return ViewState["SelectType"] != null?(SelectDateType)ViewState["SelectType"]:SelectDateType.DateOnly;
}
set
{
ViewState["SelectType"] = value;
}
}
/// <summary>
/// 是否使用默认的样式
/// </summary>
public bool UseDefaultStyle
{
get
{
return ViewState["UseDefaultStyle"] != null ? (bool)ViewState["UseDefaultStyle"] : true;
}
set
{
ViewState["UseDefaultStyle"] = value;
}
}
/// <summary>
/// 今天的图标Url地址
/// </summary>
[Bindable(true), Category("Appearence"), DefaultValue(""), Editor(typeof(System.Web.UI.Design.ImageUrlEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string sTodayImageUrl
{
get
{
return ViewState["sTodayImageUrl"] != null?(string)ViewState["sTodayImageUrl"]:String.Empty;
}
set
{
ViewState["sTodayImageUrl"] = value;
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
string sScript = " var gCalendarToDayUrl ="" +
this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.today.gif")
+ ""; ";
sScript += " var gCalendarCircleFillUrl ="" +
this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.circlefill.gif")
+ ""; ";
sScript += " var gCalendarToDayFillUrl ="" +
this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.todayfill.gif")
+ ""; ";
if (!this.Page.ClientScript.IsClientScriptBlockRegistered("ZfControlsCalendarDelcareJs"))
{
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ZfControlsCalendarDelcareJs", sScript, true);
}
if (this.UseDefaultStyle && !this.Page.ClientScript.IsClientScriptBlockRegistered("ZfControlsCalendarBoxCss"))
{
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ZfControlsCalendarBoxCss", "<link href="" + this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.Calendar.css") + "" rel="stylesheet" type="text/css">");
}
if ( !this.Page.ClientScript.IsClientScriptIncludeRegistered("ZfControlsCalendarJs"))
{
this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "ZfControlsCalendarJs", this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.calendar.js"));
}
string strVBSCRIPT = @"<script type=""text/vbscript"">
function ZfCalendar_CheckDate(ctrl,obj)
Dim str
str = obj.Value
if isdate(str) then
obj.IsValid = true
Else
obj.IsValid = false
end if
end function
</script>
";
if (!this.Page.ClientScript.IsClientScriptBlockRegistered("ZfControlsCalendarJs"))
{
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ZfControlsCalendarJs", strVBSCRIPT,false);
}
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
if (this.Context != null)
{
if (this.sTodayImageUrl == "")
{
this.sTodayImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.today.gif");
}
}
if (this.ImageUrl == "")
{
this.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "ZFControls.Resource.calendar.gif");
}
this.txtInput = new TextBox();
this.txtInput.ID = "txt"+this.ID ;
this.txtInput.CssClass = this.CssClass;
if (this.Width == Unit.Empty && this.SelectType == SelectDateType.DateOnly)
{
this.txtInput.Width = Unit.Parse("70px");
}
else
{
this.txtInput.Width = this.Width;
}
HtmlTable tb = new HtmlTable();
tb.Border = 0;
tb.CellPadding = 0;
tb.CellSpacing = 0;
tb.Style.Add("display", "inline");
HtmlTableRow row = new HtmlTableRow();
HtmlTableCell cell = new HtmlTableCell();
row.Cells.Add(cell);
tb.Rows.Add(row);
cell.Controls.Add(this.txtInput);
System.Web.UI.HtmlControls.HtmlImage img = new System.Web.UI.HtmlControls.HtmlImage();
img.Attributes.Add("onclick","javascript:GoSelectDate(this,'"+this.ClientID+"')");
img.Attributes.Add("class",this.ImageCssClass);
img.Src = this.ImageUrl;
cell = new HtmlTableCell();
row.Cells.Add(cell);
cell.Controls.Add(img);
this.Controls.Add(tb);
if(this.NotNull)
{
RequiredFieldValidator req = new RequiredFieldValidator();
req.ControlToValidate = txtInput.ID;
req.ErrorMessage = "日期不可空";
req.Display = ValidatorDisplay.Dynamic;
this.Controls.Add(req);
}
CustomValidator cu = new CustomValidator();
cu.ControlToValidate = txtInput.ID;
cu.ErrorMessage = "日期格式不正确";
cu.ClientValidationFunction = "ZfCalendar_CheckDate";
this.Controls.Add(cu);
base.OnInit (e);
}
/// <summary>
///
/// </summary>
/// <param name="writer"></param>
public override void RenderBeginTag(HtmlTextWriter writer)
{
//base.RenderBeginTag (writer);
}
/// <summary>
///
/// </summary>
/// <param name="writer"></param>
public override void RenderEndTag(HtmlTextWriter writer)
{
//base.RenderBeginTag (writer);
}
/// <summary>
/// 将此控件呈现给指定的输出参数。
/// </summary>
/// <param name="output"> 要写出到的 HTML 编写器 </param>
protected override void Render(HtmlTextWriter output)
{
output.Write("<span SelectType=""+ (int)this.SelectType +"">");
base.Render(output);
if (this.Context == null) return;
string sHTML = @"<span onselectstart=""javascript:return false;"" style=""display:none;position:absolute;width:200px;background-color:#d6e3f7;border:solid 1px #336699;border-bottom:solid 2px gray;border-right:solid 2px gray;padding:5px;"" onclick=""javascript:ShowCalendar(event,this,'{0}');"">
<div style='text-align:center'>
<FONT style=""CURSOR: hand;font-weight:bold"" color=black eid=""1""><</FONT><input id='txtYear{0}' eid=""5"" onclick=""return "" onblur=""javascript:return ShowCalendar(event,this,'{0}');"" style=""text-align:center;border:none;width:35px;background-color:transparent;padding-bottom:2px;height:15px"" maxlength=""4"" ondblclick=""this.focus();this.style.backgroundColor='white';this.style.borderColor='#336699';this.style.borderStyle='solid';this.style.borderWidth='1'"" value=""2007"" ></input>年
<FONT style=""CURSOR: hand;font-weight:bold"" color=black eid=""2"">></FONT> <FONT style=""CURSOR: hand;font-weight:bold"" color=black eid=""3""><</FONT>
<SPAN style=""CURSOR: default"" onclick='javascript:CalendarShowMonths(""{0}"",this)'><input id='txtMonth{0}' style=""text-align:center;border:none;width:16px;background-color:transparent;padding-bottom:2px;height:15px;cursor:default"" readonly></input>月</SPAN>
<FONT style=""CURSOR: hand;font-weight:bold"" color=black eid=""4"">></FONT>
</div>
<div id=""divList{0}"" ></div>
</span>";
sHTML = String.Format(sHTML, this.ClientID);
output.Write(sHTML);
;
output.Write(@"<table id=""TbCalendar"+this.ClientID+@""" onclick=""javascript:ShowCalendar(event,this,'"+this.ClientID+@"');"" class=""tblMonths"" style=""display:none;cursor:default"" >
<tr>
<td value=""1"" eid=""12"">一月</td>
<td value=""2"" eid=""12"">二月</td>
<td value=""3"" eid=""12"">三月</td>
</tr>
<tr>
<td value=""4"" eid=""12"">四月</td>
<td value=""5"" eid=""12"">五月</td>
<td value=""6"" eid=""12"">六月</td>
</tr>
<tr>
<td value=""7"" eid=""12"">七月</td>
<td value=""8"" eid=""12"">八月</td>
<td value=""9"" eid=""12"">九月</td>
</tr>
<tr>
<td value=""10"" eid=""12"">十月</td>
<td value=""11"" eid=""12"">十一月</td>
<td value=""12"" eid=""12"">十二月</td>
</tr>
</table>");
output.Write("</span>");
}
}
/// <summary>
/// 控件选择日期的类型
/// </summary>
public enum SelectDateType
{
/// <summary>
/// 选择日期
/// </summary>
DateOnly = 1,
/// <summary>
/// 选择日期时间
/// </summary>
DateTime = 2,
/// <summary>
/// 只选择时间
/// </summary>
TimeOnly = 3
}
}
将js、css、gif等文件编辑到dll中,是为了使用方便,这样做理论上效率可能会差些,但实际上应该不大。
calendar.js文件:
var gMaxZIndex = 1000;
function GetElePos(e)
{
var t=e.offsetTop;
var l=e.offsetLeft;
while(e=e.offsetParent){
t+=e.offsetTop;
l+=e.offsetLeft;
}
return [l, t];
}
function GoSelectDate(img,clientid)
{
var el = img.parentNode;
var type = el.SelectType;
var div = document.getElementById("divList"+clientid);
var spanParent = div.parentNode;
var txt = document.getElementById("txt"+clientid);
var value = txt.value;
var dt = new Date();
var y = dt.getFullYear();
var m = dt.getMonth()+1;
var d = dt.getDate();
if(value != "")
{
var reg = new RegExp(/^(d{4})-(d+)-(d+)$/);
if(reg.exec(value) != null)
{
var a = reg.exec(value);
y = a[1];
m = a[2];
d = a[3];
}
}else
{
d= 0;
}
if(parseInt(m)<1 || parseInt(m)>12)
{
m = dt.getMonth()+1;
}
div.setAttribute("year",y);
div.setAttribute("month",m);
div.setAttribute("day",d);
spanParent.style.cssText = "position:absolute;width:200px;height:200px;background-color:#d6e3f7;border:solid 1px #336699;border-bottom:solid 2px gray;border-right:solid 2px gray;padding:5px;";
var str = GetCalendarHTML(y,m,d,clientid,y,m,d);
SaveDivDate(div,y,m,d,clientid);
div.innerHTML = str;
var ary = GetElePos(img);
spanParent.style.left = ary[0];
if(ary[0]+ spanParent.offsetWidth>document.body.offsetWidth)
{
spanParent.style.left = document.body.offsetWidth-spanParent.offsetWidth;
}
spanParent.style.top = ary[1]+img.offsetHeight;
if(ary[1]+img.offsetHeight+ spanParent.offsetHeight > document.body.clientHeight)
{
spanParent.style.top = document.body.clientHeight-spanParent.offsetHeight+img.offsetHeight;
}
gMaxZIndex ++;
spanParent.style.zIndex = gMaxZIndex;
}
function ShowCalendar(evt,evtSrc,clientid)
{
var el = evt.target;
if(document.all) //ie
{
el = evt.srcElement;
}
var eid = el.getAttribute("eid");
var div = document.getElementById("divList"+clientid);
var txt = document.getElementById("txt"+clientid);
var spanParent = div.parentNode;
if(eid!= null)
{
var sely;
var selm;
var seld;
var value = txt.value;
if(value != "")
{
var reg = new RegExp(/^(d{4})-(d+)-(d+)$/);
if(reg.exec(value) != null)
{
var a = reg.exec(value);
sely = a[1];
selm = a[2];
seld = a[3];
}
}
var y = parseInt(div.getAttribute("year"));
var m = parseInt(div.getAttribute("month"));
var d = parseInt(div.getAttribute("day"));
switch(eid)
{
case "1":case "2":case "3":case "4":case "5":
if(eid == "1")
{
y -= 1;
}else if(eid == "2")
{
y+= 1;
}else if(eid == "3")
{
m -= 1;
}else if(eid == "4")
{
m += 1;
}else if(eid == "5")
{
if(isNaN(evtSrc.value))
{
return false;
}
else y = parseInt(evtSrc.value);
evtSrc.style.backgroundColor = "transparent";
evtSrc.style.borderWidth = "0";
}
if(m==0)
{
m = 12;
y -= 1;
}
if(m == 13)
{
m = 1;
y +=1;
}
SaveDivDate(div,y,m,d,clientid);
div.innerHTML = GetCalendarHTML(y,m,d,clientid,sely,selm,seld);
break;
case "12":
m = el.getAttribute("value");
SaveDivDate(div,y,m,d,clientid);
div.innerHTML = GetCalendarHTML(y,m,d,clientid,sely,selm,seld);
evtSrc.style.display = "none";
break;
case "365":
str = el.innerHTML;
str = str.replace(/<[^>]*?>/gi,"");
d = parseInt(str);
SaveDivDate(div,y,m,d,clientid);
spanParent.style.display = "none";
txt.value = get2Number(y) +"-"+ get2Number(m) +"-" +get2Number(d);
break;
}
}
}
function SaveDivDate(div,y,m,d,clientid)
{
div.setAttribute("year",y);
div.setAttribute("month",m);
div.setAttribute("day",d);
var txtYear= document.getElementById("txtYear"+clientid);
var txtMonth= document.getElementById("txtMonth"+clientid);
txtYear.value = y;
txtMonth.value = m;
}
function ConvertToInt(sValue)
{
while (sValue.length>1 && sValue.substr(0,1) =="0")
{
sValue = sValue.substr(1,sValue.length-1);
}
if(isNaN(sValue)|| sValue =="") return 0;
else return parseInt(sValue);
}
function CalendarShowMonths(clientid,span)
{
var tb = document.getElementById('TbCalendar'+clientid);
var ary = GetElePos(span);
tb.style.position = "absolute";
tb.style.display = '';
tb.style.left = ary[0]-(tb.offsetWidth/2);
tb.style.top = ary[1];
gMaxZIndex ++;
tb.style.zIndex = gMaxZIndex ;
}
function GetCalendarHTML(year,month,CurDay,clientid,sely,selm,seld)
{
var imageFolderPath = "";
var showClearDate = false;
year = parseInt(year);
month = parseInt(month);
CurDay = parseInt(CurDay);
var firstDayOfMonth =new Date(year,month-1,1);
var firstWeekDay = firstDayOfMonth.getDay();
var res ="<TABLE width='100%' border=1 cellpadding='0' cellspacing='0' class="tblCalendarCenter">";
res +="<TR class='weektr'><TD style='color:red'>日</TD><TD>一</TD><TD>二</TD><TD>三</TD><TD>四</TD><TD>五</TD><TD>六</TD></TR> ";
res +="<TR>";
for (var i=0;i<firstWeekDay;i++)
{
res +="<TD class='CalendarTd'></TD>";
}
var day =1;
var now = new Date();
for (var i=firstWeekDay;i<=6;i++,day++)
{
if(i == 0)
{
tmpClass = 'SunDayTD';
}else
{
tmpClass = 'CalendarTd';
}
if(year==now.getFullYear() && month == (now.getMonth()+1) && day == now.getDate())
{
var tmpurl = gCalendarToDayUrl;
if(day ==CurDay)
{
tmpClass += ' selectDaySpan';
tmpurl = gCalendarToDayFillUrl;
}
res +="<TD eid=365 class='"+tmpClass+"' align='center' style='font-size:12px;background-repeat:no-repeat;background-image:url("+tmpurl +");' >";
res += day;
res +="</TD>";
}
else
{
res +="<TD eid=365 align='center' ";
if(day == seld && year == sely && month == selm)
{
tmpClass += ' selectDaySpan';
res +="style='background-image:url("+gCalendarCircleFillUrl +");'";
}
res += " class='"+tmpClass+"' >";
res += day ;
res +="</TD>";
}
}
res +="</TR> ";
var cellCount=0;
var MaxDays = getMaxDayOfYearMonth(year,month);
for (;day<=MaxDays;day++,cellCount++)
{
var tmpClass="CalendarTd";
if(cellCount%7==0)
{
res +="<TR>";
tmpClass="SunDayTD";
}
;
if(year==now.getFullYear() && month == (now.getMonth()+1) && day == now.getDate())
{
tmpClass += ' selectDaySpan';
var tmpurl = gCalendarToDayUrl;
if(day ==CurDay)
{
tmpurl = gCalendarToDayFillUrl;
}
res +="<TD eid=365 class='"+tmpClass+"' align='center' style='font-size:12px;background-repeat:no-repeat;background-image:url("+tmpurl +");' >";
res += day;
res +="</TD>";
}
else
{
res +="<TD eid=365 align='center' ";
if(day == seld && year == sely && month == selm)
{
tmpClass += " selectDaySpan";
res +="style='background-image:url("+ gCalendarCircleFillUrl +")' ";
}
res += " class='"+tmpClass+"' >";
res += day ;
res +="</TD>";
}
if(cellCount %7==6)
{
res +="</TR> ";
}
}
if(res.substr(res.length-5,5) !="</TR> ")
{
var lastDay = cellCount %7;
if(lastDay !=6)
{
for (;lastDay<=6;lastDay++)
{
res +="<TD class='CalendarTd'> </TD>";
}
res +="</TR> ";
}
}
res =="</TABLE>";
var d1 = new Date();
res+="<table width='100%' border='0'><tr><td align='center'><img src='"+gCalendarToDayUrl +"'>今天:"+d1.toLocaleDateString()+ "</td></TR> ";
res +="<tr><td align='center'><a href='#' onclick='this.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.style.display="none";'>关闭</a>";
if(showClearDate!="0")
{
res +=" <a href='#' onclick='ClearDate(1);'>清除</a>";
}
res+="</td></TR> </table>";
//window.clipboardData.setData("text",res);
return res;
}
function getMaxDayOfYearMonth(year,month)
{
if(month ==2)
{
if(IsChepYear(year))
{
return 29;
}else
return 28;
}else
{
return 30+ ((month>7) + month)%2;
}
}
function IsChepYear(year)
{
if(year %4 ==0 && year % 100 !=0)
{
return true;
}else if(year % 400 ==0)
{
return true;
}else return false;
}
function get2Number(num)
{
num = parseInt(num);
if(num<10)
return "0"+num;
else return num;
}
calendar.css文件:
.SunDayTD
{
color:Red;
border-left:solid 1px #fffff1;
cursor:default;
}
.weektr
{
background-color:#000080;
height:17px;
color:White;
border-bottom:solid 1px #336699;
border-top:solid 1px gray;
text-align:center;
}
label
{
cursor:hand;
}
A
{
color:#336699;
text-decoration:none;
}
A:hover
{
color:Red;
text-decoration:none;
}
.tblMonths
{
border:solid 1px #336699;
position:absolute;
background-color:white;
}
.CalendarTd
{
border-top:solid 1px #fffff1;
border-left:solid 1px #fffff1;
font-family:Arial;
cursor:default;
}
.selectDaySpan
{
cursor:default;
color:White;
}
.tblCalendarCenter
{
border-left:none;
border-right:none;
border-collapse:collapse;
border-bottom:none;
cursor:default;
}
关于样式我就不多说了,随个人爱好修改。
calendar.gif
circlefill.gif
today.gif
totdayfill.gif
这篇博客介绍了如何创建一个自定义的日期选择控件,主要利用JavaScript实现,并将其封装为ASP.NET的自定义控件。控件的使用包括设置TextBox样式、图片样式、是否必填日期等属性。作者提供了源码和资源文件,鼓励有兴趣的读者进行改进。
3万+

被折叠的 条评论
为什么被折叠?



