DateRangePicker ( 选择带有单个扩展日历的日期范围)

分享于 

9分钟阅读

Web开发

  繁體

Sample Image - DateRangePicker.gif

介绍

自定义控件 DateRangePicker 提供了选择单个日期和任意日期范围的能力。 它是一个简单的扩展 Calendar 控件。

背景

我需要为用户提供选择日期范围的能力。 两个日历并排占据了很多空间,所以我看了一下定制控件。 我注意到 Windows 窗体允许你选择日期范围,但是web窗体日历可以选择天。周或者月。 在互联网上有一些商业产品,但一旦我看到什么方法可以在 Calendar 上覆盖,我就知道了。

用户界面

用户首次选择某个日期时,该日期将记录为日期范围的一个结束。 然后,再次单击同一日历将设置日期范围的另一端。 再次点击将清除旧日期范围并将新日期记录为日期范围的起始点,等等。

使用代码

在自定义web控件库项目中有代码之后,只需将控件从工具箱拖到设计器上即可以。

你应该会看到类似下面的代码添加到页面:

<%@RegisterAssembly="CustomWebControls"Namespace="CustomWebControls"TagPrefix="cc1"%>...<cc1:DateRangePickerID="DateRangePicker1"runat="server"></cc1:DateRangePicker>

使用指导

有两个类组成 DateRangePicker 控件- DateRangeDateRangePickerDateRange 是表示日期范围的结构,DateRangePicker 是扩展 System.Web.UI.Calendar的自定义web控件。

DateRange

一个 DateRange 实质上是一个日期和一个到日期。 没有这个可以实现 DateRangePicker,但它帮助我们将逻辑保持在UI代码中。 它被标记为 Serializable 以便web服务能够保存在viewstate中。 最重要的逻辑方法是 Include,它将 DateTime 或者其他 DateRange 添加到实例。 当单击第二个 DateTime 时,我们使用这里选项,这意味着用户不必先单击最早的日期。 EqualsHashCode 和运算符 = == 是否全部重写以提高效率。

using System;namespace CustomWebControls
{
 [Serializable]
 publicstruct DateRange
 {
 publicstaticreadonly DateRange EMPTY = new DateRange();
 readonly DateTime from;
 readonly DateTime to;
 public DateRange(DateTime from, DateTime to)
 {
 this.from = from;
 this.to = to;
 }
 public DateTime From
 {
 get { returnfrom; }
 }
 public DateTime To
 {
 get { return to; }
 }
 public TimeSpan TimeSpan
 {
 get {
 return to - from;
 }
 }
 publicbool Contains(DateTime time)
 {
 returnfrom<= time && time < to;
 }
 public DateRange Include(DateRange otherRange)
 {
 return Include(otherRange.From).Include(otherRange.To);
 }
 public DateRange Include(DateTime date)
 {
 if (date <from)
 returnnew DateRange(date, to);
 elseif (date > to)
 returnnew DateRange(from, date);
 else 
 returnthis;
 }
 ///<summary>/// Creates a one day (24 hr) long DateRange starting at DateTime///</summary>publicstatic DateRange CreateDay(DateTime dateTime){
 returnnew DateRange(dateTime, dateTime.AddDays(1));
 }
 #region operators and overridespublicoverrideint GetHashCode()
 {
 returnfrom.GetHashCode() + 29*to.GetHashCode();
 }
 publicoverridebool Equals(object obj)
 {
 if (ReferenceEquals(this, obj)) returntrue;
 if (!(obj is DateRange)) returnfalse;
 DateRange dateRange = (DateRange) obj;
 if (!Equals(from, dateRange.from)) returnfalse;
 if (!Equals(to, dateRange.to)) returnfalse;
 returntrue;
 }
 publicstaticbooloperator == (DateRange d1, DateRange d2)
 {
 return d1.Equals(d2);
 }
 publicstaticbooloperator!=(DateRange d1, DateRange d2)
 {
 return!d1.Equals(d2);
 }
 #endregion }
}

DateRangePicker

这是重写日历的类。 它有两个属性,一个用于样式化选定的DateRange,另一个用于存储选定的DateRange。

默认情况下,样式的BackColorLightSteelBlue。 这是在 static 构造函数中初始化的。 样式存储在 private 变量中,因为每当初始化 Page 时,新样式都将由设计器代码设置。 但是,SelectedDateRange 存储在ViewState中,因为它需要跨多个页面请求。 如果不使用 ViewState,则需要找到另一种方法来保持这里变量。

OnSelectionChanged 是我们改变 DateRange的地方。 OnDayRender 是我们将样式应用到 DateRange的地方。 注意 OnSelectionChanged 中整个天的特殊处理。

using System.ComponentModel;using System.Drawing;using System.Web.UI;using System.Web.UI.WebControls;namespace CustomWebControls
{
 ///<summary>/// An extended Calendar that can select DateRanges as well as Dates///</summary> [DefaultProperty("Text")]
 [ToolboxData("<{0}:DateRangePicker runat="server"></{0}:DateRangePicker>")]
 publicclass DateRangePicker : Calendar
 {
 staticreadonly TableItemStyle defaultSelectedDateRangeStyle = new TableItemStyle();
 static DateRangePicker()
 {
 //initialise a default colour for defaultSelectedDateRangeStyle defaultSelectedDateRangeStyle.BackColor = Color.LightSteelBlue;
 }
 TableItemStyle selectedDateRangeStyle = defaultSelectedDateRangeStyle;
 protectedoverridevoid OnDayRender(TableCell cell, CalendarDay day)
 {
 if (SelectedDateRange.Contains(day.Date))
 {
 cell.ApplyStyle(selectedDateRangeStyle);
 }
 }
 protectedoverridevoid OnSelectionChanged()
 {
 base.OnSelectionChanged();
 bool emptyDateRange = SelectedDateRange == DateRange.EMPTY;
 bool dateRangeAlreadyPicked = SelectedDateRange.TimeSpan.TotalDays >1;
 if (emptyDateRange || dateRangeAlreadyPicked)
 {
 SelectedDateRange = DateRange.CreateDay(SelectedDate);
 //save this date as the first date in our date range }
 else {
 SelectedDateRange = 
 SelectedDateRange.Include(DateRange.CreateDay(SelectedDate));
 //set the end date in our date range }
 }
 //DateRange gets stored in the viewstate since//it's a property that needs to persist across page requests. <Browsable(false)>public DateRange SelectedDateRange
 {
 get { return (DateRange) (ViewState["SelectedDateRange"]??99DateRange.EMPTY); }
 set { ViewState["SelectedDateRange"] = value; }
 }
 //SelectedDateRangeStyle goes into a private//variable since this property is designed. [Category("Styles")]
 [Description("The Style that is aplied to cells within the selected Date Range")]
 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
 [NotifyParentProperty(true)]
 [PersistenceMode(PersistenceMode.InnerProperty)]
 public TableItemStyle SelectedDateRangeStyle
 {
 get { return selectedDateRangeStyle; }
 set { selectedDateRangeStyle = value; }
 }
 }
}

6. 今后工作

  • 更好的设计人员支持。
  • OnDayRender的进一步扩展,让用户更多的工具提示。
  • 你的建议我重视所有反馈。 如果你觉得这适合你,或者你愿意提供任何改进,我愿意听。

ext  CAL  Select  Extend  日期  日历  
相关文章