Multi-Select Calendar with a Date Range

For a recent assignment I found myself desiring an Asp.Net calendar control with the ability to select multiple non-contiguous dates over a specific range of dates. Specifically, I needed only weekdays within the next two weeks to be available dates. I had a difficult time finding a whole lot of information on the subject so I’ve decided to throw this out there for all of you.

So without further ado, let’s jump into the code. We’ll start by defining our calendar.

<asp:Calendar ID="calExample" runat="server" 
CssClass="Calendar"
NextPrevStyle-CssClass="NextPrevStyle" 
DayStyle-CssClass="DayStyle"
TitleStyle-CssClass="Title" 
DayHeaderStyle-CssClass="DayHeader"
OtherMonthDayStyle-CssClass="OtherMonthDay" 
SelectedDayStyle-CssClass="DayStyle"
OnSelectionChanged="calExample_SelectionChanged" 
OnDayRender="calExample_DayRender" ></asp:Calendar>

The styles aren’t terribly important, except for:

SelectedDayStyle-CssClass="DayStyle"

This will be important later on when we want to use our own date selection rather than the default.

Next we’ll set up up the dates that we don’t want to selectable by using the OnDayRender event.

 DateTime MinDate = DateTime.Today;
 DateTime MaxDate = DateTime.Today.AddDays(14);
if ((e.Day.Date < MinDate) || (e.Day.Date > MaxDate) || (e.Day.IsWeekend))
{
    e.Day.IsSelectable = false;
    e.Cell.CssClass = "OtherMonthDay";
}

We set the IsSelectable property to false to prevent selection and we use the OtherMonthDay style to maintain consistency with other unselectable dates.

So far everything has been pretty painless right? Good, because this where things start to get a little wacky. Not too wacky mind you but we have to start being clever. The goal here is to be able to select a date by clicking on it, and deselect a date that is selected by clicking on it again. The first order of business is to make use of the OnSelectionChanged event Like so:

 protected void calExample_SelectionChanged(object sender, EventArgs e)
{
            int index = -1;
            List<DateTime> SelectedDates = ViewState["SelectedDates"] as List<DateTime>;

            if (SelectedDates == null)
            {
                SelectedDates = new List<DateTime>();
            }

            index = SelectedDates.IndexOf(calExample.SelectedDate);
            //select any unselected dates            
            if (index < 0)
            {
                SelectedDates.Add(calExample.SelectedDate);
            }
            //Remove any already selected dates
            else
            {
                SelectedDates.RemoveAt(index);
            }

            ViewState.Add("SelectedDates", SelectedDates);
}
&#91;/code&#93;
As you see we are just retrieving our list of dates from the viewstate and adding or removing the selected dates as necessary.  Finally we need to flesh out our OnDayRender event to display our dates properly.  
&#91;code language="csharp"&#93;
protected void calExample_DayRender(object sender, DayRenderEventArgs e)
{
            List<DateTime> SelectedDates = ViewState["SelectedDates"] as List<DateTime>;

            if (SelectedDates == null)
            {
                SelectedDates = new List<DateTime>();
            }

            DateTime MinDate = DateTime.Today;
            DateTime MaxDate = DateTime.Today.AddDays(14);
            if ((e.Day.Date < MinDate) || (e.Day.Date > MaxDate) || (e.Day.IsWeekend))
            {
                e.Day.IsSelectable = false;
                e.Cell.CssClass = "OtherMonthDay";
            }

            if (SelectedDates.Contains(e.Day.Date))
            {
                e.Cell.CssClass = "SelectedDay";
            }

            calExample.SelectedDate = DateTime.MinValue;
}

This should be fairly self explanatory too. The only thing I’d like to highlight here is:

     calExample.SelectedDate = DateTime.MinValue;

This is important, because if we didn’t programatically reset the selected date, then susbsequent clicks on the most recently selected date would not fire the OnSelectionChanged event.

So there you have it, a multi-select calendar with a date range. I recognize that this is actually a relatively naive implementation. I am currently working on a refactoring this idea into a custom control or possibly an AJAX based server control that I’ll gladly discuss in a future post. Let me know in the comments if you have any preferences on which of those I post about. Also, I’ve got a sample project available if anyone is interested.

Advertisements
Explore posts in the same categories: .NET, C#

2 Comments on “Multi-Select Calendar with a Date Range”

  1. Daryl Hemeon Says:

    Hi,

    Great job! I’m interested seeing and/or hearing about the AJAX based version of this idea.

    Thanks!

  2. Thomas Says:

    Great…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: