自定义日期输入控件-解决需要用户输入日期的麻烦控制
一般情况下使用文本框的,由于但无法很好的控制用户输入的格式通常都会写一个输入格式的说明如:1999-12-12,虽然用多个组合的下拉菜单可以解决问题,但是似乎不太方便操作。后来用梅花雨的日期控件,确实很好用,并且样式也很好控制,梅花雨使用了比较复杂的客户端控制代码实现了很美好的用户感受(不知道现在的版本是否解决),但是当需要输入日期的控件存在于框架中的时候会出现客户端的错误。
在一般的项目中需要输入日期的地方只是引导用户正确的输入正确的日期格式以及验证。因此自己些了个简单使用的.net webform下的日期控件。功能方面提供日期菜单的定位、样式、以及跨度,但为了灵活控制目前没有做验证,通过修改限制用户输入或则增加正则表达式的判断即可进行用户输入的控制。
以下是源码部分:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
namespace PublicControls
{
///<summary>
/// DateBox 的摘要说明。
///</summary>
public class DateBox : Control,IPostBackDataHandler,IPostBackEventHandler
{
#region预定义
private string text;
private int startyear=2000;
private int steps=1;
private string divcssclass;
private string fontcssclass;
private string textboxcssclass;
private TempStyle template;
private Unit width,height;
private bool autopostback=false;
public event EventHandler OnValueChanged;
#endregion
#region属性
[Description("自动回送")]
public bool AutoPostBack
{
get
{
if(ViewState["AutoPostBack"]!=null)
autopostback = (bool)ViewState["AutoPostBack"];
return autopostback;
}
set
{
ViewState["AutoPostBack"]=value;
autopostback = (bool)ViewState["AutoPostBack"];
}
}
[Description("文本框宽度")]
public Unit Width
{
get
{
if(ViewState["Width"]!=null)
width=(Unit)ViewState["Width"];
return width;
}
set
{
ViewState["Width"]=value;
width=(Unit)ViewState["Width"];
}
}
[Description("文本框高度")]
public Unit Height
{
get
{
if(ViewState["Height"]!=null)
height=(Unit)ViewState["Height"];
return height;
}
set
{
ViewState["Height"]=value;
height=(Unit)ViewState["Height"];
}
}
[Description("日期字符串")]
public string Text
{
get
{
text=(string)ViewState["Text"];
return text;
}
set
{
ViewState["Text"]=value;
text=(string)ViewState["Text"];
}
}
[Description("起始年份")]
public int StartYear
{
get
{
if(IsNumeric(ViewState["StartYear"]))
startyear=(int)ViewState["StartYear"];
return startyear;
}
set
{
ViewState["StartYear"]=value;
startyear=(int)ViewState["StartYear"];
}
}
[Description("年份跨度")]
public int Steps
{
get
{
if(IsNumeric(ViewState["Steps"]))
steps=(int)ViewState["Steps"];
return steps;
}
set
{
ViewState["Steps"]=value;
steps=(int)ViewState["Steps"];
}
}
[Description("背景CSS样式")]
public string divCssClass
{
get
{
divcssclass=(string)ViewState["divCssClass"];
return divcssclass;
}
set
{
ViewState["divCssClass"]=value;
divcssclass = (string)ViewState["divCssClass"];
}
}
[Description("文字CSS样式")]
public string fontCssClass
{
get
{
fontcssclass=(string)ViewState["fontCssClass"];
return fontcssclass;
}
set
{
ViewState["fontCssClass"]=value;
fontcssclass = (string)ViewState["fontCssClass"];
}
}
[Description("文本框CSS样式")]
public string textboxCssClass
{
get
{
textboxcssclass=(string)ViewState["textboxCssClass"];
return textboxcssclass;
}
set
{
ViewState["textboxCssClass"]=value;
textboxcssclass = (string)ViewState["textboxCssClass"];
}
}
[Description("模板样式")]
public TempStyle Template
{
set
{
template=value;
if(template!=TempStyle.None)
{
divCssClass="TemplateCssClass";
fontCssClass="TemplateCssClass";
textboxCssClass="TemplateCssClass";
}
else
{
divCssClass="";
fontCssClass="";
textboxCssClass="";
}
ViewState["Template"]=template;
}
get
{
return template;
}
}
[Description("X方向偏移量")]
public int excursionX
{
get
{
if(IsNumeric(ViewState["excursionX"]))
return (int)ViewState["excursionX"];
else
return 0;
}
set
{
ViewState["excursionX"]=value;
}
}
[Description("Y方向偏移量")]
public int excursionY
{
get
{
if(IsNumeric(ViewState["excursionY"]))
return (int)ViewState["excursionY"];
else
return 0;
}
set
{
ViewState["excursionY"]=value;
}
}
#endregion
#region事件和方法
public bool LoadPostData(string postDataKey, NameValueCollection values)
{
if(values[this.UniqueID].ToString()==Text)
{
return false;
}
else
{
Text=values[this.UniqueID];
return true;
}
}
public void RaisePostBackEvent(string e)
{
}
public void RaisePostDataChangedEvent()
{
ValueChanged();
}
///<summary>
///将事件委托给所调用的页面
///</summary>
public void ValueChanged()
{
if(OnValueChanged!=null)
{
OnValueChanged(this,System.EventArgs.Empty);
}
}
#endregion
#region输出
///<summary>
///将此控件呈现给指定的输出参数。
///</summary>
///<param name="output">要写出到的 HTML 编写器 </param>
protected override void Render(HtmlTextWriter output)
{
int j=1;
StringBuilder view=new StringBuilder("");
view.Append(CssString(this.Template));
view.Append("<input class=/""+this.textboxCssClass+"/" id=/""+this.UniqueID+"/" name=/""+this.UniqueID+"/" value=/""+this.Text+"/" style=/"Width:"+this.Width+";Height:"+this.Height+"/" onfocus=/""+this.UniqueID+"_show(this)/">");
//组合年部分
view.Append("<div class=/""+this.divCssClass+"/" id=/""+this.UniqueID+"_year/" style=/"Z-INDEX: 9999; POSITION: absolute;display:none/">");
view.Append("请选择年份:<br>");
for(int i=0;i<this.Steps;i++)
{
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this)/" style=/"CURSOR: hand/">"+(this.StartYear+i)+"</font>");
if(j==4)
{
view.Append("<br>");
j=1;
}
else
{
if(i+1!=this.Steps)
view.Append(",");
j++;
}
}
view.Append("</div>");
//组合月部分
view.Append("<div class=/""+this.divCssClass+"/" id=/""+this.UniqueID+"_month/" style=/"Z-INDEX: 9999; POSITION: absolute;display:none/">");
view.Append("请选择月份:<br>");
j=1;
for(int i=0;i<12;i++)
{
if(i<9)
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this)/" style=/"CURSOR: hand/">0"+(i+1)+"</font>");
else
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this)/" style=/"CURSOR: hand/">"+(i+1)+"</font>");
if(j==6)
{
view.Append("<br>");
j=1;
}
else
{
if(i+1!=12)
view.Append(",");
j++;
}
}
view.Append("</div>");
//组合日部分
view.Append("<div class=/""+this.divCssClass+"/" id=/""+this.UniqueID+"_day/" style=/"Z-INDEX: 9999; POSITION: absolute;display:none/">");
view.Append("请选择日期:<br>");
j=1;
for(int i=0;i<31;i++)
{
if(this.AutoPostBack)
{
if(i<9)
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this);"+Page.GetPostBackEventReference(this,"")+";/" style=/"CURSOR: hand/">0"+(i+1)+"</font>");
else
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this);"+Page.GetPostBackEventReference(this,"")+";/" style=/"CURSOR: hand/">"+(i+1)+"</font>");
}
else
{
if(i<9)
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this);/" style=/"CURSOR: hand/">0"+(i+1)+"</font>");
else
view.Append("<font class=/""+this.fontCssClass+"/" onclick=/""+this.UniqueID+"_sign(this);/" style=/"CURSOR: hand/">"+(i+1)+"</font>");
}
if(j==8)
{
view.Append("<br>");
j=1;
}
else
{
if(i+1!=31)
view.Append(",");
j++;
}
}
view.Append("</div>");
view.Append(@"
<script language=javascript>
<!--
function $sign$(obj)
{
if(document.all.$TextBoxID$.value!='')
document.all.$TextBoxID$.value+='-'+obj.innerHTML;
else
document.all.$TextBoxID$.value+=obj.innerHTML;
obj.parentNode.nextSibling.style.display='block';
obj.parentNode.nextSibling.style.posTop=obj.parentNode.offsetTop;
obj.parentNode.nextSibling.style.posLeft=obj.parentNode.offsetLeft;
obj.parentNode.style.display='none';
}
function $show$(obj)
{
obj.value='';
obj.nextSibling.style.display='block';
obj.nextSibling.nextSibling.style.display='none';
obj.nextSibling.nextSibling.nextSibling.style.display='none';
obj.nextSibling.style.posTop=obj.offsetTop+20+$excursionY$;
obj.nextSibling.style.posLeft=obj.offsetLeft+$excursionX$;
}
//-->
</script>
");
view.Replace("$TextBoxID$",this.UniqueID.ToString());
view.Replace("$sign$",this.UniqueID.ToString()+"_sign");
view.Replace("$show$",this.UniqueID.ToString()+"_show");
view.Replace("$excursionX$",this.excursionX.ToString());
view.Replace("$excursionY$",this.excursionY.ToString());
output.Write(view);
}
#endregion
#region其他函数
public bool IsNumeric(object obj)
{
obj += "";
string str = obj.ToString();
//判断是否为空
if (str == null || str.Length==0)
{
return false;
}
//循环检查每个字符
foreach(char c in str)
{
if (!Char.IsNumber(c))
{
return false;
}
}
return true;
}
public enum TempStyle
{
None,
Default,
Light
}
public string CssString(TempStyle ts)
{
StringBuilder css=new StringBuilder("");
switch(ts)
{
case TempStyle.None:
break;
case TempStyle.Default:
css.Append("<style type=/"text/css/">");
css.Append(@"<!--
div.TemplateCssClass
{
background-color:White;
border-bottom-width:thin;
border-bottom-color:Black;
border-bottom-style:solid;
border-top-width:thin;
border-top-color:Black;
border-top-style:solid;
border-left-width:thin;
border-left-color:Black;
border-left-style:solid;
border-right-width:thin;
border-right-color:Black;
border-right-style:solid;
padding-bottom:3px;
padding-left:3px;
padding-right:3px;
padding-top:3px;
}
font.TemplateCssClass
{
background-color:White;
}
input.TemplateCssClass
{
}
-->
</style>
");
break;
case TempStyle.Light:
css.Append("<style type=/"text/css/">");
css.Append(@"<!--
div.TemplateCssClass
{
background-color:White;
border-bottom-width:thin;
border-bottom-color:normal;
border-bottom-style:solid;
border-top-width:thin;
border-top-color:normal;
border-top-style:solid;
border-left-width:thin;
border-left-color:normal;
border-left-style:solid;
border-right-width:thin;
border-right-color:normal;
border-right-style:solid;
padding-bottom:3px;
padding-left:3px;
padding-right:3px;
padding-top:3px;
font-size:9pt;
filter:alpha(opacity=60);
}
font.TemplateCssClass
{
event:expression(
onmouseover=function()
{
this.style.backgroundColor='#0066FF';
this.style.color='#ffffff';
},
onmouseout=function()
{
this.style.backgroundColor='#ffffff';
this.style.color='#000000';
}
)
}
input.TemplateCssClass
{
}
-->
</style>
");
break;
}
return css.ToString();
}
#endregion
}
}
需要注意的是,当控件在单页面中的时候excursionX excursionY偏移属性保持为0就可以了(当然如果你想设置不同的菜单的位置设置其他数字也是可以的),当控件在框架的时候,默认的偏移属性会产生一定的偏差,这时调整偏移量属性进行定位。