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

ASP.NET 日历增强版,适用于 JS 和移动设备

starIconstarIconstarIconstarIconstarIcon

5.00/5 (5投票s)

2017年6月13日

CPOL

5分钟阅读

viewsIcon

14448

downloadIcon

544

一个响应式、支持 JavaScript 的事件日历,使用 ASP.NET 日历控件

引言

这是一个简单(但优雅、轻量且响应式)的事件日历,使用 ASP.NET 日历控件、一个 UpdatePanel(以避免完整的页面回发)以及一些 jQuery,用于显示所选日期的事件。

背景

我需要为用户提供一个简单的事件日历,但我不需要或不需要一个“完整”的、包含多日事件的日历。我的用户在其他屏幕上购买他们的活动参与,所以这个日历只是为了以视觉化的方式整合他们购买的所有活动,以便在任何设备上都能轻松查看。

市面上有许多事件日历插件(搜索一下就能找到几十种),但我需要一些非常轻量级的,并且不想安装和集成第三方软件包。所以,我改编了内置的 ASP.NET 日历。

Using the Code

默认的 ASP.NET 日历控件(未经样式化)看起来是这样的

这不够精致,也不够用户友好,所以第一步是构建带有类名的控件,以便可以使用样式表。

我在日历周围添加了一个“calendarWrapperdiv,这样我就可以给它一个漂亮的容器。

<div class="calendarWrapper">
   <asp:Calendar ID="Calendar1" 
   runat="server" CssClass="myCalendar" 
   DayNameFormat="Short" Font-Names="Tahoma"
      OnDayRender="Calendar1_DayRender" 
      OnVisibleMonthChanged="Calendar1_VisibleMonthChanged" 
      cellspacing="0" cellpadding="0" title="Calendar" 
      style="border-width: 1px; border-style: solid; font-family: Tahoma; 
      border-collapse: collapse;">
          <OtherMonthDayStyle CssClass="calDay otherMonthDay" />
          <DayStyle CssClass="calDay" />
          <DayHeaderStyle CssClass="calDayHeader" 
          ForeColor="#2d3338" />
          <SelectedDayStyle Font-Bold="True" 
          CssClass="calDaySelected" />
          <TodayDayStyle CssClass="calToday" />
          <SelectorStyle CssClass="calSelector" />
          <NextPrevStyle CssClass="calNextPrev" />
          <TitleStyle CssClass="calTitle" />
   </asp:Calendar>
</div>

有了我的样式表,结果是这样的

请注意,这里大量使用了 CSS3 -- 你可以在上面的图片中看到两个阴影。外部的浅蓝色边框是包装器 div(添加了阴影),这为日历增添了漂亮的收尾效果。

CSS 文件包含在 ZIP 文件中,你可以随意修改它以获得想要的结果 -- 本文将更侧重于 JS 和代码隐藏部分,以及如何最大限度地减少数据库活动。

由于我的用户在一个月内可能有几十个事件,我预计他们可能会点击日历来查看每一天。我想避免每次点击都访问数据库,所以我决定提前检索所有事件,然后使用 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 中,或者一个 tooltip-style 的弹出窗口)。我选择使用 42 个隐藏字段,对应于日历日期,来存储 string。然后,我只需要每次点击时调用一个 JS 函数来显示被点击日期对应的事件。

为了做到这一点,我们必须替换每个 date-cell 内部锚标签中的 __doPostBack 调用。这需要实现控件的 DayRender 事件,我们在其中用一个新的锚标签替换现有的锚标签。

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)
{
   DateTime thisDate = e.Day.Date.Date;
   .
   .
   e.Cell.Text = string.Format("<a href='#' 
   onclick='Showday(this,{0});return false;' title='{1}'>{2}</a>",
               _dayIndex.ToString(), thisDate.ToString
               ("dddd, MMMM d, yyyy"), thisDate.Day.ToString());
   .
   .
}

锚标签的标题设置为一个长日期字符串,原因有两个:

  1. 当用户将鼠标悬停在日期上时,工具提示将显示标题,并且
  2. Showday” JS 函数可以获取标题并在页面上的其他地方填充标签,以增强用户视觉体验。

当然,"{2}" 参数就是日期本身,用户在日历中可以看到它,并且它在 CSS 中进行了样式化。

接下来,我想高亮显示所有包含事件的日期,以便用户知道点击/触摸哪里。在 DayRender 方法中,我只需向单元格的类名添加“ActivityDay”,然后使用 CSS 为其添加一个背景图像。

可以使用任何高亮方法,例如背景颜色,只需修改 CSS 即可。

移动设备

CSS 文件为最大宽度为 600 的显示设置了较小的日历及其单元格尺寸。(不要忘记在标记文件中添加“viewport” meta 标签。)如果想让它变得更小,可以调整这些值,但如果单元格变得比指尖还小,日历将很快变得难以导航。

此外,你可能会在 CSS 文件中看到一些“:hover”条目(现在已注释掉),以便在鼠标光标经过单元格时给它们一个浅灰色背景。然而,iOS 设备不喜欢 hover 样式,甚至可能拒绝识别在具有 hover 样式的锚标签上的手指点击。通过在代码隐藏中添加 onmouseoveronmouseout 事件并删除 hover CSS 来解决这个问题。我们获得了相同的效果,而不会冒犯 iPhone 或 iPad。

关注点

显然,我在代码隐藏中经历了一些曲折,以尽量避免数据库调用。另一种方法是在用户每次点击日期时进行 AJAX 调用。这可以避免初始数据库查询,但之后每次点击都会产生数据库命中。这是权衡。在需要点击时检索大量数据的情况下,基于 AJAX 的方法可能更好。

可下载的 ZIP 文件包含一个功能齐全的网站项目,使用 VS 2010 完成。我最初是在 VS 2015 中创建的,但希望它能在早期版本中使用。

大部分 CSS 是从其他文章中拼凑而成的。如果你在别处看到它(或类似的),很可能 THAT 是原始来源。

历史

  • 2017年6月13日:初始发布
© . All rights reserved.