ASP.NET MVC3:创建一个自定义日历/日期选择器






4.93/5 (8投票s)
为您的项目创建您自己的自定义日历/日期选择器
引言
在本文中,我们将向您展示如何在 ASP.NET MVC3 中创建一个自定义日历。这些步骤很简单,遵循 MVC 范例,从创建模型到在月份之间导航。
背景
社区中存在一些日期选择器插件,开发人员可以在他们的应用程序中使用,一个流行的例子是 Jquery 日期选择器插件。然而,我们可能会遇到需要自定义日期选择器(或者我们称之为日历)以合并要显示的数据甚至样式的场景。当然,您可以修改任何插件的代码以适应您的场景;但是,构建您自己的自定义日历更容易,它可以使您的应用程序与众不同。一个场景的例子是,HIS 应用程序需要在每个日期显示每日患者和治疗,开发人员首先想到的就是我们需要构建自己的日期选择器。
如果自定义日历以显示数据,例如插入每天的简单通知。
使用代码
- 创建一个模型 - CalendarModel。
- 创建一个服务类,用于日期的逻辑和转换。
- 创建一个控制器和调用服务的操作。
- 创建一个视图,可以显示当前月份。
- 创建一个 JavaScript(jQuery 库)来在月份之间导航
让我们从创建一个名为 CalendarModel 的新模型开始,该模型定义了此项目所需的类。
public class WeekForMonth
{
public List<Day> Week1 { get; set; } //days for week1
public List<Day> Week2 { get; set; } //days for week2
public List<Day> Week3 { get; set; } //days for week3
public List<Day> Week4 { get; set; } //days for week4
public List<Day> Week5 { get; set; } //days for week5
public List<Day> Week6 { get; set; } //days for week6
public string nextMonth { get; set; }
public string prevMonth { get; set; }
}
public class Day
{
public DateTime Date { get; set; }
public string _Date { get; set; }
public string dateStr { get; set; }
public int dtDay { get; set; }
public int? daycolumn { get; set; }
}
创建一个服务文件夹和类(我们称之为 CalendarManager.cs)来执行日期的后端逻辑和转换。服务类包含几个用于计算日历中日期、日期和日期列的函数。首先,我们需要调用 getDates(year,month) 函数来获取所选月份和年份的每个日期,然后通过 GetWeekOfMonth(DateTime date) 知道该日期属于该月的哪一周。通过使用 getCalendar 函数返回 WeekForMonth 的模型来完成我们的服务,该函数将每个月的每一天和星期数映射起来。
//main function to arrange each details of day into a month, function returns a list of weeks for a month
public WeekForMonth getCalender(int month, int year)
{
WeekForMonth weeks = new WeekForMonth();
weeks.Week1 = new List<Day>();
weeks.Week2 = new List<Day>();
weeks.Week3 = new List<Day>();
weeks.Week4 = new List<Day>();
weeks.Week5 = new List<Day>();
weeks.Week6 = new List<Day>();
List<DateTime> dt = new List<DateTime>();
dt = GetDates(year, month);
foreach (DateTime day in dt)
{
switch (GetWeekOfMonth(day))
{
case 1:
Day dy1 = new Day();
dy1.Date = day;
dy1._Date = day.ToShortDateString();
dy1.dateStr = day.ToString("MM/dd/yyyy");
dy1.dtDay = day.Day;
dy1.daycolumn = GetDateInfo(dy1.Date);
weeks.Week1.Add(dy1);
break;
case 2:
Day dy2 = new Day();
dy2.Date = day;
dy2._Date = day.ToShortDateString();
dy2.dateStr = day.ToString("MM/dd/yyyy");
dy2.dtDay = day.Day;
dy2.daycolumn = GetDateInfo(dy2.Date);
weeks.Week2.Add(dy2);
break;
case 3:
Day dy3 = new Day();
dy3.Date = day;
dy3._Date = day.ToShortDateString();
dy3.dateStr = day.ToString("MM/dd/yyyy");
dy3.dtDay = day.Day;
dy3.daycolumn = GetDateInfo(dy3.Date);
weeks.Week3.Add(dy3);
break;
case 4:
Day dy4 = new Day();
dy4.Date = day;
dy4._Date = day.ToShortDateString();
dy4.dateStr = day.ToString("MM/dd/yyyy");
dy4.dtDay = day.Day;
dy4.daycolumn = GetDateInfo(dy4.Date);
weeks.Week4.Add(dy4);
break;
case 5:
Day dy5 = new Day();
dy5.Date = day;
dy5._Date = day.ToShortDateString();
dy5.dateStr = day.ToString("MM/dd/yyyy");
dy5.dtDay = day.Day;
dy5.daycolumn = GetDateInfo(dy5.Date);
weeks.Week5.Add(dy5);
break;
case 6:
Day dy6 = new Day();
dy6.Date = day;
dy6._Date = day.ToShortDateString();
dy6.dateStr = day.ToString("MM/dd/yyyy");
dy6.dtDay = day.Day;
dy6.daycolumn = GetDateInfo(dy6.Date);
weeks.Week6.Add(dy6);
break;
};
}
while (weeks.Week1.Count < 7) // not starting from sunday
{
Day dy = null;
weeks.Week1.Insert(0, dy);
}
if (month == 12)
{
weeks.nextMonth = (01).ToString() + "/" + (year + 1).ToString();
weeks.prevMonth = (month - 1).ToString() + "/" + (year).ToString();
}
else if (month == 1)
{
weeks.nextMonth = (month + 1).ToString() + "/" + (year).ToString();
weeks.prevMonth = (12).ToString() + "/" + (year - 1).ToString();
}
else
{
weeks.nextMonth = (month + 1).ToString() + "/" + (year).ToString();
weeks.prevMonth = (month - 1).ToString() + "/" + (year).ToString();
}
return weeks;
}
//get all dates for a month for the year specified
public static List<DateTime> GetDates(int year, int month)
{
return Enumerable.Range(1, DateTime.DaysInMonth(year, month)) // Days: 1, 2 ... 31 etc.
.Select(day => new DateTime(year, month, day)) // Map each day to a date
.ToList();
}
//get number of week for the selected month by passing in a date value
public static int GetWeekOfMonth(DateTime date)
{
DateTime beginningOfMonth = new DateTime(date.Year, date.Month, 1);
while (date.Date.AddDays(1).DayOfWeek != DayOfWeek.Sunday)
date = date.AddDays(1);
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
}
//translate each day to a day number for mapping to week
public int GetDateInfo(DateTime now)
{
int dayNumber = 0;
DateTime dt = now.Date;
string dayStr = Convert.ToString(dt.DayOfWeek);
if (dayStr.ToLower() == "sunday")
{
dayNumber = 0;
}
else if (dayStr.ToLower() == "monday")
{
dayNumber = 1;
}
else if (dayStr.ToLower() == "tuesday")
{
dayNumber = 2;
}
else if (dayStr.ToLower() == "wednesday")
{
dayNumber = 3;
}
else if (dayStr.ToLower() == "thursday")
{
dayNumber = 4;
}
else if (dayStr.ToLower() == "friday")
{
dayNumber = 5;
}
else if (dayStr.ToLower() == "saturday")
{
dayNumber = 6;
}
return dayNumber;
}
在我们的 Home Controller 中创建一个控制器并调用服务。我们需要一个用于初始页面的操作结果和一个异步控制器,用于 ajax 调用以返回我们下个月/上个月的日历模型。
public ActionResult Index()
{
var model = _calendar.getCalender(DateTime.Now.Month, DateTime.Now.Year);
return View(model);
}
//for ajax request
public ActionResult AsyncUpdateCalender(int month, int year)
{
if (HttpContext.Request.IsAjaxRequest())
{
var model = _calendar.getCalender(month, year);
return Json(model, JsonRequestBehavior.AllowGet);
}
else
{
return View();
}
}
创建一个视图页面,生成日历 html 表格形式。视图页面需要强类型模型 WeekForMonth。视图页面必须添加 C# 代码来循环模型中的项目到我们的表格中,id="component-table"用于显示。注意:请参考显示的图像以获得我们的日历显示,以便更清楚地查看 html 的结果。我们有标题(用于月份名称和导航)和内容(用于日期显示)。
@model Calendar.Models.WeekForMonth
<div id="component-header">
<a id="@Model.prevMonth"
class="month" style="float:left;margin-left:10px;">Prev</a>
@DateTime.Now.ToString("MMM") @DateTime.Now.Year <a id="@Model.nextMonth"
class="month" style="float:right;margin-right:10px;">Next</a>
</div>
<div>
<table id="component-table">
<thead>
<tr>
<th>
Sun
</th>
<th>
Mon
</th>
<th>
Tue
</th>
<th>
Wed
</th>
<th>
Thurs
</th>
<th>
Fri
</th>
<th>
Sat
</th>
</tr>
</thead>
<tbody>
<tr id="week1">
@foreach (var item in Model.Week1)
{
if (item != null)
{
if (item.daycolumn == 0 || item.daycolumn == 6)
{
<td class="weekend"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else if (item.Date != DateTime.Today)
{
<td><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else
{
<td class="selected"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
}
else
{
<td></td>
}
}
</tr>
<tr id="week2">
@foreach (var item in Model.Week2)
{
if (item != null)
{
if (item.daycolumn == 0 || item.daycolumn == 6)
{
<td class="weekend"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else if (item.Date != DateTime.Today)
{
<td><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else
{
<td class="selected"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
}
else
{
<td></td>
}
}
</tr>
<tr id="week3">
@foreach (var item in Model.Week3)
{
if (item != null)
{
if (item.daycolumn == 0 || item.daycolumn == 6)
{
<td class="weekend"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else if (item.Date != DateTime.Today)
{
<td><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else
{
<td class="selected"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
}
else
{
<td></td>
}
}
</tr>
<tr id="week4">
@foreach (var item in Model.Week4)
{
if (item != null)
{
if (item.daycolumn == 0 || item.daycolumn == 6)
{
<td class="weekend"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else if (item.Date != DateTime.Today)
{
<td><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else
{
<td class="selected"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
}
else
{
<td></td>
}
}
</tr>
<tr id="week5">
@foreach (var item in Model.Week5)
{
if (item != null)
{
if (item.daycolumn == 0 || item.daycolumn == 6)
{
<td class="weekend"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else if (item.Date != DateTime.Today)
{
<td><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else
{
<td class="selected"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
}
else
{
<td></td>
}
}
</tr>
<tr id="week6">
@if (Model.Week6 != null)
{
foreach (var item in Model.Week6)
{
if (item != null)
{
if (item.daycolumn == 0 || item.daycolumn == 6)
{
<td class="weekend"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
else if (item.Date != DateTime.Today)
{
<td><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3></a></td>
}
else
{
<td class="selected"><a id="@item.dateStr"
class="dt"><h3>@item.dtDay</h3> </a></td>
}
}
else
{
<td></td>
}
}
}
</tr>
</tbody>
</table>
</div>
JavaScript(jquery 库)使用 ajax 调用在单击上个月或下个月时进行即时更新。该脚本的示例也可以在项目文件中找到。该脚本通过异步调用操作结果来获取下个月/上个月的数据,清空初始表中的数据,最后将新数据分配到表中来实现。
单击上一个/下一个链接将触发一个事件到 AsyncUpdateCalendar,通过 ajax 调用。我们清空现有表的每一周,循环遍历收到的结果,并按周数追加结果。
$(".month").live('click', function () {
var object = $(this).attr("id");
var str = object.split('/');
// str[0] contains "month"
// str[1] contains "year"
$.ajax
({
url: '../../Home/AsyncUpdateCalender',
type: 'GET',
traditional: true,
contentType: 'application/json',
data: { month: str[0], year: str[1] },
success: function (result) {
if (!jQuery.isEmptyObject(result)) {
var week1 = $("#week1");
week1.empty();
var week2 = $("#week2");
week2.empty();
var week3 = $("#week3");
week3.empty();
var week4 = $("#week4");
week4.empty();
var week5 = $("#week5");
week5.empty();
var week6 = $("#week6");
week6.empty();
var newHeader = $('<a id=' + result.prevMonth + ' class="month" ' +
'style="float:left">Prev</a>' + getMonth(str[0]) + ' ' +
str[1] + '<a id=' + result.nex tMonth +
' class="month" style="float:right">Next</a>');
$("#component-header").empty();
$("#component-header").append(newHeader);
$.each(result.Week1, function (i, item) {
var htmlStr = null;
if (jQuery.isEmptyObject(item)) {
htmlStr = $('<td></td>');
week1.append(htmlStr);
} else {
if (item.daycolumn == 0 || item.daycolumn == 6) {
htmlStr = $('<td class="weekend"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3></a>');
}
else if (item._Date != getTodayDate()) {
htmlStr = $('<td></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3></a>');
} else {
htmlStr = $('<td class="selected"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3></a>');
}
week1.append(htmlStr);
}
});
$.each(result.Week2, function (i, item) {
var htmlStr = null;
if (jQuery.isEmptyObject(item)) {
htmlStr = $('<td></td>');
week2.append(htmlStr);
} else {
if (item.daycolumn == 0 || item.daycolumn == 6) {
htmlStr = $('<td class="weekend"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
else if (item.Date != getTodayDate()) {
htmlStr = $('<td></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
} else {
htmlStr = $('<td class="selected"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
week2.append(htmlStr);
}
});
$.each(result.Week3, function (i, item) {
var htmlStr = null;
if (jQuery.isEmptyObject(item)) {
htmlStr = $('<td></td>');
week3.append(htmlStr);
} else {
if (item.daycolumn == 0 || item.daycolumn == 6) {
htmlStr = $('<td class="weekend"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
else if (item.Date != getTodayDate()) {
htmlStr = $('<td></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
} else {
htmlStr = $('<td class="selected"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' +
item.dtDay + '</h3> </a>');
}
week3.append(htmlStr);
}
});
$.each(result.Week4, function (i, item) {
var htmlStr = null;
if (jQuery.isEmptyObject(item)) {
htmlStr = $('<td></td>');
week4.append(htmlStr);
} else {
if (item.daycolumn == 0 || item.daycolumn == 6) {
htmlStr = $('<td class="weekend"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
else if (item.Date != getTodayDate()) {
htmlStr = $('<td></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
} else {
htmlStr = $('<td class="selected"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
week4.append(htmlStr);
}
});
$.each(result.Week5, function (i, item) {
var htmlStr = null;
if (jQuery.isEmptyObject(item)) {
htmlStr = $('<td></td>');
week5.append(htmlStr);
} else {
if (item.daycolumn == 0 || item.daycolumn == 6) {
htmlStr = $('<td class="weekend"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
else if (item.Date != getTodayDate()) {
htmlStr = $('<td></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
} else {
htmlStr = $('<td class="selected"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
week5.append(htmlStr);
}
});
$.each(result.Week6, function (i, item) {
var htmlStr = null;
if (jQuery.isEmptyObject(item)) {
htmlStr = $('<td></td>');
week6.append(htmlStr);
} else {
if (item.daycolumn == 0 || item.daycolumn == 6) {
htmlStr = $('<td class="weekend"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
else if (item.Date != getTodayDate()) {
htmlStr = $('<td></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
} else {
htmlStr = $('<td class="selected"></td>');
htmlStr.append('<a id=' + item.dateStr +
' class="dt"><h3>' + item.dtDay + '</h3> </a>');
}
week6.append(htmlStr);
}
});
$("#component-table").trigger("update");
} else {
alertMsg('Oops, errors occur in retrieving calender');
}
}
});
});
最终输出必须使用 css 进行样式设置,并可能在 html 属性中进行分配。创建自己的自定义日历/日期选择器的主要挑战包括正确计算周数,将日期映射到日期和周,以及根据所选月份更新日历。注意:要在同一图块中为每一天进行通知,您可能需要在 getCalendar 函数中添加更多服务逻辑,并修改 html 中的每一行周以显示项目。
关注点
我们想强调的主要观点是,使用 C# 和 jquery 构建自定义日历/日期选择器并不难。它为您的应用程序增加了独特性,并且我们的方法可以应用于构建约会/日程安排应用程序。例如,我们将日历设计成带有数据的图块,并且日期位于同一图块上,您可以根据您的场景在任何图块上添加通知消息。
贷方
感谢 RabbitChemo 团队的 Dwee Chee Siong 先生(实习生)和 Kenovan Cheok 先生(后端工程师)编译所有必要的开源贡献信息。