在本文中,将探讨如何使用ASP.NET内置的日历控件来创建一个轻量级的事件日历。这个日历旨在为用户提供一个直观的方式来查看他们购买的各种活动,而不需要一个功能复杂的全日历。用户通过其他页面购买参与活动,因此日历的主要作用是将所有已购买的活动以视觉化的方式整合在一起,方便在任何设备上查看。
尽管市面上有许多事件日历插件可供选择,但作者需要的是一个非常轻量级的解决方案,并且更倾向于不安装和集成第三方包。因此,作者对内置的ASP.NET日历控件进行了调整。默认的ASP.NET日历控件(未加样式)看起来可能不是很精致或用户友好,因此第一步是为控件添加类名,以便可以使用样式表。
作者在日历周围添加了一个名为"calendarWrapper"的div,以便为它提供一个好看的容器。通过样式表,结果如下所示:注意这里大量使用了CSS3——可以看到图片上的两个阴影效果。外围的浅蓝色边框是包装div(添加了阴影),这为日历增添了不错的装饰效果。
由于用户在一个月内可能有许多活动,作者预计他们会在日历上点击以查看每一天。为了避免每次点击时对数据库的访问,作者提前检索所有活动,以便使用JS(jQuery)在点击/触摸时立即显示一天的内容。无需回发,无需数据库查询,无需延迟。
提前查询活动信息是具有挑战性的,因为没有办法询问日历控件它的日期范围,以知道要查询哪些日子。甚至不能在初始加载时询问它当前的月份,尽管这很容易计算出来(DateTime.Now.Month)。然而,控件总是显示6周,或42天——默认情况下从周日开始,所以作者使用了一个扩展方法来计算控件预期的第一天:
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek) {
int diff = dt.DayOfWeek - startOfWeek;
if (diff < 0) {
diff += 7;
}
return dt.AddDays(-1 * diff).Date;
}
...这提供了开始日期,所以只需添加42就可以得到结束日期。然后,使用这个日期范围来查询数据库中适用的活动。
接下来,需要将事件信息发送到浏览器,以便JavaScript代码可以显示它(可能在另一个div中,或者是一个工具提示样式的弹出窗口)。作者选择了42个隐藏字段,对应日历的日期,以保存字符串。然后只需要每次点击就调用一个JS调用来显示被点击日期的活动。
为了实现这一点,需要替换每个日期单元格内锚标签中的__doPostBack调用。这需要实现控件的DayRender事件,用一个新的锚标签替换它:
protected void Calendar1_DayRender(object sender, DayRenderEventArgs e) {
DateTime thisDate = e.Day.Date.Date;
...
e.Cell.Text = string.Format(
"",
_dayIndex.ToString(), thisDate.ToString(
"dddd, MMMM d, yyyy"), thisDate.Day.ToString());
...
}
锚标题设置为长日期字符串有两个原因:当用户悬停在日期上时,将显示标题的工具提示,并且"Showday" JS函数可以获取标题并在页面上的其他地方填充一个标签,以便于用户视觉识别。
当然,作者还希望突出显示所有包含活动的日期,以便用户知道在哪里点击/触摸。在DayRender方法中,作者只需为单元格添加"ActivityDay"类名,然后使用CSS为其添加背景图像: 任何突出显示方法都可以使用,例如背景颜色,只需修改CSS即可。
移动设备:CSS文件为最大宽度600像素的显示指定了较小的尺寸。(不要忘记在标记文件中添加"viewport"元标签。)可以调整这些值,如果想让它更小,但日历将很快变得难以导航,如果单元格变得比指尖还小。
还会注意到CSS文件中的一些":hover"条目(现在已注释掉),以在鼠标光标经过时为单元格添加浅灰色背景。然而,iOS设备不喜欢悬停样式,甚至可能拒绝在具有悬停样式的锚上承认手指点击。通过使用代码后台添加onmouseover和onmouseout事件,并移除悬停CSS,可以解决这个问题。得到了相同的效果,而不会冒犯iPhone或iPad。
显然,作者在代码后台跳过了一些步骤,以尽可能减少数据库调用。另一种方法是在用户每次点击日期时进行AJAX调用。这可以避免初始的数据库查询,但然后会在每次点击时产生数据库击中。权衡。基于AJAX的方法在需要在点击时检索更多数据的情况下可能更好。