在开发类似于Outlook 2007的个人日历/预约日历时,需要一个月份日历。市面上有许多优秀的日历控件,但它们并不完全符合需求。因此,开始开发自己的日历控件。在这个过程中,不仅实现了一个月历,还实现了一个日期选择器控件。
同时,考虑将文化适应性(culture awareness)集成到控件中,以便不同国家的人们也可以使用。这比想象的要复杂得多,遇到了很多关于文化支持的问题,包括框架中的一些棘手的错误;稍后会有更详细的说明。
想在这里分享结果,因为CodeProject多次为问题提供了解决方案。
在DatePicker控件中有一个新属性AllowPromptAsInput。将其设置为true允许输入包括当前日期分隔符在内的日期,该分隔符由FormatProvider属性设置。
文化适应性 - 意味着可以设置使用的文化和日历;
通过CalendarDimensions属性可调整可见子日历的数量;
在颜色和字体方面完全可定制;
可以加载或保存颜色表;
可调整RTL或LTR布局;
可以调整是否使用最短或缩写的星期名称;
可以调整是否显示周头和周尾;
可调整非工作日(对于工作周选择模式);
可调整每周的第一天;
可调整星期名称(完整/缩写/最短);
可调整月份名称(完整/缩写);
可调整月份/天字符串模式;
支持设置最小/最大日期;
使用鼠标滚轮滚动;
不同的选择模式(单日/工作周/整周/手动);
可调整手动选择模式下最多可选的天数;
加粗日期集合;
新的:扩展的加粗日期(类别和相应的颜色定义);
新的:手动选择模式现在支持使用CTRL键选择多个范围;
新的:日期分隔符现在在选择器控件中有效输入;
可调整滚动变化(点击箭头时滚动多少个月);
日期选择器控件支持键盘导航;
支持禁用状态;
只需将控件项目添加到现有解决方案中并引用它。该控件是用VS 2010构建的,目标框架版本是3.5。
关于控件的文化适应性,必须承认不能保证所有内容都正确显示和计算。如果有错误,请随时发布消息。
如前所述,在实现文化适应性时,遇到了框架中的一些棘手的错误。其中一个错误如下:
System.Globalization.Calendar实现中的GetWeekOfYear()方法。每个日历都有一个MinSupportedDateTime属性。如果想从该日期获取年份的周数,那么在某些情况下,尽管传递给方法的日期是有效的,但会得到一个ArgumentOutOfRangeException。
受影响的日历实现有:
Hijri、UmAlQura、Hebrew、Persian、JulianCalendar,以及所有EastAsianLunisolarCalendar的实现。
另一个错误是在日本日历中,GetYear()方法对于特定日期范围返回0。
很可能没有找到所有关于日历实现的错误,所以如果设置了一个不寻常的日历,如JapaneseLunisolarCalendar,可能会抛出异常。
控件的渲染由一个单独的渲染器类处理。如果想要自定义绘图,那么可以通过派生自抽象基类或默认渲染器来实现自己的渲染器。
对于实现IXmlSerializable的颜色表类也是如此。
需要注意的一点是,只能设置非中性文化。原因是中性文化没有DateTimeFormat属性的值,需要这个值用于不同的原因。
要调整可见的子月视图,可以直接设置CalendarDimensions属性,或者使用设计器。
使用ColorTable属性,可以调整使用的颜色,包括是否使用渐变颜色和渐变模式。
选择器文本框部分中的日期使用短日期模式显示,也可以调整这个模式。这个模式也用于解析日期。
选择器控件有一个CheckDate事件,可以在其中检查并设置输入的日期是否有效。如果无效,则使用InvalidBackColor和InvalidForeColor属性的颜色显示日期。
另一个重要属性是ClosePickerOnDayClick。通过它,可以调整选择器是否在点击一天时关闭,无论该天是否已经被选中。
DatePicker和MonthCalendar控件现在有两个新属性:
BoldedDateCategoryCollection BoldedDatesCollection
第一个集合保存加粗日期的类别定义,第二个集合保存加粗日期及其对应的类别。
定义加粗日期的原始属性仍然像以前一样工作。
两个控件都有一个新属性:
UseNativeDigits
这个属性将控件中显示的任何数字转换为包含当前Culture的NativeDigits的字符串。
如果将当前Culture设置为波斯语(fa-IR),那么这个文化就没有阿拉伯数字,而是波斯数字。
例如,波斯语日期01.01.1390在格式dd/MM/yyyy中将显示为:
۰۱ / ۰۱ / ۱۳۹۰
让向展示一张设置日期选择器的Culture和CultureCalendar为波斯语的图片:
此外,手动输入的日期也使用原生数字。
请注意,显示的星期名称(可能还有月份名称)可能是错误的,因为这些值是从.Net Framework CultureInfo类中获取的,特别是波斯语(fa-IR)CultureInfo类的波斯语星期名称(在这种情况下是最短的星期名称)是错误的,这是由于波斯语(fa-IR)CultureInfo类的一个错误/特性。
月控件有以下重要事件:
DateChanged:通过上下文菜单更改月份或年份时发生;
DateClicked:在'Day'选择模式下点击一天时发生;
DateSelected:选择日期或日期范围时发生;
SelectionExtendEnd:选择扩展结束时发生;
日期选择器有一个重要事件:
ValueChanged:日期值更改时发生;
两个控件有一个共同的事件:
ActiveDateChanged:当鼠标悬停在一个日期上时发生。
2009年12月1日:初次发布。
2011年10月12日:扩展了带类别的加粗日期。
2011年11月22日:扩展了支持多个范围的选择。