65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET DatePicker 用户控件(回历/公历)将月份和年份显示为下拉列表

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (39投票s)

2013 年 4 月 3 日

CPOL

5分钟阅读

viewsIcon

185668

downloadIcon

11300

基于日历控件的 ASP.NET 日期选择器用户控件。

您可以在此处试用在线演示。

引言

我正在开发一个使用日期选择器处理出生日期和有效期等日期字段的应用程序。有些字段应以回历或公历输入,因为在沙特阿拉伯,官方日历是回历,许多人只知道他们的回历日期。因此,我需要一个日期选择器控件,允许用户选择日历(回历或公历),最后在文本框中填写两个日期。

我尝试通过开发此用户控件来实现上述目标。希望它对任何对回历日期选择器感兴趣的人都有用。

后来我遇到了一些延迟问题,因为在回历和公历之间切换时会导致服务器端回发,我开发了另一个完全在客户端使用 JavaScript 工作的控件,详情请参阅新文章(支持回历和公历的基于 JavaScript 的日期用户控件)。

Ajax Toolkit Datepicker 控件有什么问题?

我正在寻找一个支持回历和公历的 AJAX 或 jQuery 日期选择器。此外,将月份和年份显示为下拉列表,而不是静态的月份/年份标题,以方便在大时间范围内导航。不幸的是,我没有找到任何支持回历的控件,而且 Ajax 控件工具包日期选择器(在此处)在回历年份导航方面存在一个错误。

伊斯兰(回历)日历简介

伊斯兰日历、穆斯林日历或回历(AH)是农历,一年有 12 个月,共 354 或 355 天。由于它是一个纯粹的农历,因此它与季节不同步。每年漂移 10 或 11 天,季节关系大约每 33 个伊斯兰年(每 32 个太阳年)重复一次。

它被用于许多穆斯林国家(与公历同时)的事件日期,并被世界各地的穆斯林用于确定斋月、朝觐以及庆祝其他伊斯兰节日和假期的正确日期。

第一年是公元 622 年开始的伊斯兰年,在此期间,先知穆罕默德(愿他安息)从麦加迁徙到麦地那,史称希吉拉(Hijra)。每个编号的年份都以 H 表示希吉拉或 AH 表示拉丁语 anno Hegirae(在希吉拉之年)[3],因此穆斯林通常将他们的日历称为回历。

当前的伊斯兰年是回历 1434 年。在公历中,回历 1434 年大约从 2012 年 11 月 14 日持续到 2013 年 11 月 4 日。

使用代码 

只需将用户控件拖放到您的 ASPX 页面中,将 ScriptManger 添加到您的 ASPX 页面中,并将日历图像添加到您的解决方案中。有关在 ASP.NET 网页中包含用户控件的更多信息

用户控件属性

该控件公开了六个属性:DefaultCalendarCultureSelectedCalendareDategetHijriDateTextgetGregorianDateTextMinYearCountFromNowMaxYearCountFromNow,可在宿主页面中使用。

公开默认日历文化并显示小的 Intellisense 框弹出选项(回历、公历)。

Intellisense

//To set the default Calendar to Hijri 
<uc1:HijriGregDatePicker ID="HijriGregDatePicker1" 
  runat="server"  DefaultCalendarCulture="Arabic" >

//To set the default Calendar to Gregorian from Source
<uc1:HijriGregDatePicker ID="HijriGregDatePicker2" 
  runat="server"  DefaultCalendarCulture="English" >

//To set the default Calendar to Hijri from Code
HijriGregDatePicker1.DefaultCalendarCulture =DatePicker.DefaultCultureOption.Arabic;

//To set the default Calendar to Gregorian from Code
HijriGregDatePicker1.DefaultCalendarCulture =DatePicker.DefaultCultureOption.English;

//Note that if you have multiple instances from the userconrtrol
//you have to give all of instances the same default culture
//otherwise you will got inconvenient behaviour

您可以获取选定的回历日期

HijriGregDatePicker1.SelectedCalendareDate.ToString(strDateFormat, 
   new CultureInfo("ar-SA").DateTimeFormat); 

您可以获取选定的公历日期

HijriGregDatePicker1.SelectedCalendareDate.ToString(strDateFormat, 
   new CultureInfo("en-US").DateTimeFormat);

您可以从数据库设置日期

if (!IsPostBack)
{
    DataView dvDataView = (DataView)SqlDataSource1.Select(DataSourceSelectArguments.Empty);
    HijriGregDatePicker1.SelectedCalendareDate = (DateTime)dvDataView[0][0];   
}

从回历文本框中获取回历日期

string strHijri = HijriGregDatePicker1.getHijriDateText; 

从公历文本框中获取公历日期

string strGreg = HijriGregDatePicker1.getGregorianDateText;

设置年份下拉列表中允许选择的最小年份

//To set the minimum year to 2003
HijriGregDatePicker1.MinYearCountFromNow = -10;

设置年份下拉列表中允许选择的最大年份

//to set the maximum year to 2023
HijriGregDatePicker1.MaxYearCountFromNow = 10;
  1. DefaultCalendarCulture

  2. SelectedCalendareDate

  3. getHijriDateText

  4. getGregorianDateText

  5. MinYearCountFromNow

  6. MaxYearCountFromNow

解决方案

我依赖 ASPX 日历控件来开发此解决方案,主要问题是日历控件根据页面文化加载,并且无法在不更改页面文化的情况下更改日历文化。

为此,我创建了一个用户控件,使其行为类似于日期选择器,通过更改页面文化的下拉列表在不同文化之间切换。我还将此用户控件放在 UpdatePanel 中,以便部分更新日历而不影响当前页面。

换句话说,我可以这样说,因为我们不能在单个页面中设置两种不同的文化,所以此解决方案是一种变通方法,允许用户在同一页面中使用多个日历。

同一页面中用户控件的多个实例

允许多个实例对我来说是一个巨大的挑战。因为我必须管理所有实例的回发和文化更改。例如,如果回发是由文化下拉列表、年份下拉列表或月份下拉列表触发的,则日历 div 将保持可见,但如果由其他控件触发,则日历 div 状态将更改为隐藏。

//To get the potpack control name
private string getPostBackControlName()
{
    Control control = null;
    //first we will check the "__EVENTTARGET" because if post back made by the controls
    //which used "_doPostBack" function also available in Request.Form collection.
    string ctrlname = Page.Request.Params["__EVENTTARGET"];
    if (ctrlname != null && ctrlname != String.Empty)
    {
        control = Page.FindControl(ctrlname);
    }

    if (control == null)
    {
        return string.Empty;
    }
    else
    {
        //to catch the control name in case of multiple instances
        return control.UniqueID;
    }
}

用户控件 JavaScript

此用户控件的 JavaScript 非常简单,如下所示

//To Show hide the div when user click on calendar image or any date text boxes
<script type="text/javascript">
    function showHide(div) {
        if (document.getElementById(div).style.display == "none") {
            document.getElementById(div).style.display = "block";
        }
        else { document.getElementById(div).style.display = "none"; }
    }
</script>
//to hide the date picker when user click outside the date picker box
<script type="text/javascript">
document.onclick = function (e) {
    e = e || event
    var target = e.target || e.srcElement
    var box = document.getElementById('<% =this.whole_calendar.ClientID %>')
    var imgCal = document.getElementById('<% =this.imgCalendar.ClientID %>')
    var txtHijri = document.getElementById('<% =this.txtHijri.ClientID %>')
    var txtGreg = document.getElementById('<% =this.txtGreg.ClientID %>')
    do {
        if (box == target | imgCal == target | txtHijri == target | txtGreg == target) {
            // Click occured inside the box, do nothing.
            return
        }
        target = target.parentNode
    }
    while (target)
    // Click was outside the box, hide it.
    box.style.display = "none"
}
</script>
  1. 显示/隐藏日历日期选择器
  2. 当用户单击日期选择器框外部的任何位置时隐藏日期选择器

使用验证控件

您可以使用验证控件来验证选定的日期,例如,我使用自定义验证器来检查选定的日期是否应介于 2015/01/01 和 2016/12/31 之间。

    <script type="text/javascript">
    // to validate date between two dates note that date format MM/dd/yyyy
    function checkDate(source, arguments) {
        var minDate = new Date('01/01/2015');
        var maxDate = new Date('12/31/2016');
        var selTxtDate = document.getElementById('<% =this.HijriGregDatePicker1.FindControl("txtGreg").ClientID %>').value;
        var CurrentDate = new Date(selTxtDate.substr(3, 2) + "/" + selTxtDate.substr(0, 2) + "/" + selTxtDate.substr(6, 4));
        if (CurrentDate - minDate > 0 && CurrentDate - maxDate < 0)
        {
            arguments.IsValid = true;
        }
        else
        {
            arguments.IsValid = false;
        }
    }
    </script>    
<asp:CustomValidator ID="dateCustomvalidator" runat="server" ControlToValidate="HijriGregDatePicker1:txtGreg" ClientValidationFunction="checkDate" Display="Dynamic" SetFocusOnError="True" ErrorMessage="The date shoud be between 01/01/2015 and 12/31/2016" ForeColor="Red"  />    

关注点

请注意,当您更改日期选择器文化(回历到公历或反之)时,您也会更改页面文化。因此,如果您正在使用资源文件(本地化),我建议您在页面加载时将页面文化保存在隐藏字段中,并在提交时将其取回,如下所示

protected void Page_Load(object sender, EventArgs e)
{
    hidCulture.Value = CultureInfo.CurrentCulture.ToString();
}

protected void btnSubmit_Click(object sender, EventArgs e)
{
    System.Globalization.CultureInfo culture = 
            System.Globalization.CultureInfo.CreateSpecificCulture(hidCulture.Value);
    System.Threading.Thread.CurrentThread.CurrentCulture = culture;
    System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
}

局限性

请注意,如果您只想将日历用于单一文化,那么您可以禁用更改文化的下拉列表。但是,如果您的应用程序中有多种文化,则不能强制用户只选择特定文化中的日期,因为其他用户控件实例将受到影响,并且页面文化的任何更改都将影响日历。

浏览器兼容性

此控件已在最新版本的 Firefox、Internet Explorer、Chrome 和 Safari 上进行了测试

最后

我尽力使此用户控件没有错误。欢迎提出任何意见、想法和建议,以进一步改进此用户控件。

参考文献

历史

  • 版本 1.0:2013 年 3 月 31 日。
© . All rights reserved.