Wednesday, October 2, 2013

Create Custom Calendar in MVC

There are several plugins out there that can help you to create a calendar in MVC, JQuery, and other languages, but one disadvantage to all of these is a lack of customization.  In searching the web, I noticed that not many articles have been written about this topic, so here's one example.

This article will help you get started in creating a fully customizable HtmlHelper method to use throughout your application in MVC.  I prefer MVC4, but it will work with version 3 as well.

First, create a static class and name it whatever.  Mine is called DataControls, but it isn't important.  The only reason for the static method is so that you can use it as an MVC helper class in your view.

The class looks like this:

using System;
using System.Globalization;
using System.Text;
using System.Web.Mvc;
public static class DataControls
    {
        public enum DayFormat
        {
            Long, Medium, Short
        }

        public static MvcHtmlString Calendar(
  this HtmlHelper helper,
  DayFormat dayFormat,
  int month, int year)
        {
            DateTime today = DateTime.Now;
            int daysInMonth = DateTime.DaysInMonth(year, month);
            string[] dayNames = new string[] { };
            switch (dayFormat)
            {
                case DayFormat.Medium:
                    dayNames = new string[] { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" };
                    break;
                case DayFormat.Short:
                    dayNames = new string[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" };
                    break;
                case DayFormat.Long:
                    dayNames = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
                    break;
                default:
                    throw new Exception("Please specify a Day Format.");
            }
            StringBuilder calendar = new StringBuilder();
            calendar.Append(string.Format("

", "calendar"));

            calendar.Append("");
            calendar.Append(" ");
            for (int i = 0; i < dayNames.Length; i++)
            {
                calendar.Append(string.Format("{0}", dayNames[i]));
            }
            calendar.Append("
");            calendar.Append("
");            calendar.Append("");
            for (int i = 1; i <= 42; i++)
            {
                if (i % 7 == 1)
                {
                    calendar.Append(" ");
                }
                calendar.Append("");
                DateTime firstDay = new DateTime(year, month, 1);
                int firstDayOfWeek = (int)CultureInfo
        .InvariantCulture.Calendar.GetDayOfWeek(firstDay);
                if (i > firstDayOfWeek && (i - firstDayOfWeek) <= daysInMonth)
                {
                    calendar.Append(i - firstDayOfWeek);
                }
                calendar.Append("
");                if (i % 7 == 7)
                {
                    calendar.Append("
");                }
            }
            calendar.Append("
");            calendar.Append("
");            return MvcHtmlString.Create(calendar.ToString());
        }
    }

In a nutshell, we are creating a table that allows us to specify a format for month names, and then doing a loop to determine what day of week each day falls on, as well as how many days occur in the selected month and year.  If you don't care about the format of the days, you don't have to use the enum, but I like to allow for customization.

Once this is created, you can simply call this function inside of your razor view by calling:

(This would generate a calendar for January of 2013)
@Html.Calendar(DataControls.DayFormat.Medium, 1, 2013)

Obviously, you'd want to create a filter mechanism for displaying months and years to the user so they could select a month and year, but that is outside of the scope of this article.  Personally, I created an array and displayed dropdowns in my page for them to select from, but just as easily, you could create custom links for them to select from as well.  Use your imagination.

Good luck with this, and if you have any questions, feel free to contact me via my homepage at: Joshua Blackstone.Com or comment below.

Thanks.

0 comments: