Home > ASP.NET, C#, MVC3, Razor > ASP.NET MVC Calendar

ASP.NET MVC Calendar

Wersja polska poniżej

I was creating booking system for one of my clients, everything went pretty smooth until he asked for calendar that would display the dates that are unavailable to pick, booked but not confirmed yet and booked and confirmed – all these in different styles. After some research I did I’ve found that none of the tools like jquery or mootools plugins worked for me the way I wanted them to work. So I’ve decided to create my own Calendar user control.

Thinking what I would need I came to list of following variables :

  • month/year to display
  • number of days in month to display
  • what day of week are the first and last day of month to display

Normally you would want this information to be part of Model / ViewModel but to make things simple we’ll put all of this into cshtml ( yeah, we’ll be using Razor and MVC3). First things first, so let’s create a new View in

/Views/Shared folder by name of “_ReservationCalendar.cshtml”

@{
DateTime firstDay = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
int daysInCurrentMonth = DateTime.DaysInMonth(firstDay.Year, firstDay.Month);
DateTime lastDay = new DateTime(Model.yearToShow, Model.monthToShow, daysInCurrentMonth);
// Sunday casted to int gives 0 but that will not work for us, we need 7 to be able to calculate number of empty cells correctly
int dayOfWeekFirst = ((int)firstDay.DayOfWeek > 0) ? (int)firstDay.DayOfWeek : 7;
int dayOfWeekLast = ((int)lastDay.DayOfWeek > 0) ? (int)lastDay.DayOfWeek : 7;
}

Okay, we’ve got all we need to start building HTML table for our calendar page. Let’s start with header.

<table id="reservationCalendar">
    <thead>
        <tr>
            <td>
                <<
            </td>
            <td colspan="5">
                @currentMonth @firstDay.Year
            </td>
            <td>
                >>
            </td>
        </tr>
    </thead>
    <tr>
        <td>
            Mon
        </td>
        <td>
            Tue
        </td>
        <td>
            Wed
        </td>
        <td>
            Thu
        </td>
        <td>
            Fri
        </td>
        <td>
            Sat
        </td>
        <td>
            Sun
        </td>
    </tr>

Alrighty, so we’ve got our calendar page header, showing both month and year, we’ve got days of the week columns, so let’s move to rendering dates

    <tr>
    <!-- filling up space of previous month -->
    @for (int a = 1; a < dayOfWeekFirst; a++)
    {
        @:<td></td>
    }
    <!-- filling up space of current month -->
    @for (int i = 1; i <= daysInCurrentMonth; i++)
    {
        DateTime renderedDay = new DateTime(firstDay.Year, firstDay.Month, i);

        // if Sunday
        if (renderedDay.DayOfWeek == DayOfWeek.Sunday)
        { 
            @:<td class="calendar-holiday">@i</td></tr><tr>
        }
        // if Saturday
        else if (renderedDay.DayOfWeek == DayOfWeek.Saturday)
        {
            @:<td class="calendar-holiday">@i</td>
        }
        // if normal day
        else
        {
            @:<td>@i</td>
        }   
    }
    <!-- filling up space of next month -->
    @for (int a = 1; a <= 7-dayOfWeekLast; a++)
    {
        @:<td></td>
    }
    </tr>
</table>

And that’s it. Now just add

@Html.Partial("_ReservationCalendar")

to render our partial view / user control on any page you want. There rest is really up to you, you can pass a collection of dates to be marked on your calendar from ViewModel and just place another if else for renderedDay variable. You gain control over what’s displayed and how ( do CSS magic ! ), you can add links, pop ups and whatever else you need.
That’s nothing really complex or sophisticated but maybe someone will find it useful :-)

kick it on DotNetKicks.com


Wersja polska

Jeden z moich klientów proprosił mnie o stworzenie systemu rezerwacji rzeczy różnych :-) Wszystko szło gładko dopóki nie powiedział, że najlepiej by było gdyby dostępność określonej rzeczy była przestawiona na kalendarzu. W sumie nic trudnego ale w wymaganiach pojawiły się między innymi : możliwość określenia dat dostępności, terminy, które zostały wstępnie zarezerwowane ale jeszcze nie są opłacone oraz terminy zapłacone – każdy miał być wyróżniony w inny sposób. Rozpocząłem przeszukiwanie sieci ale niestety, okazało się że istniejące kontrolki i pluginy albo nie oferują tego czego mi potrzeba, albo ich intergracja i przerabianie zajmie mi więcej czasu niż napisanie podstawy kalendarza w taki sposób abym mógł go łatwo rozbudować.
Zacząłem od określenia danych których PartialView będzie potrzebował aby “wyrenderować” mi wymarzony kalendarz.

Ostatecznie określiłem następujące zmienne

  • miesiąc i rok
  • ilość dni w wybranym miesiącu
  • dzień tygodnia dla pierwszego i ostatniego dnia miesiąca

W aplikacji te dane pewnie będziesz chciał przekazać przez ViewModel. Aby uprościć sobie życie wrzuciłem wszystko w jeden plik cshtml (ah tak, używamy MVC3 i Razora ). Dodajmy więc do projektu, w ścieżce /View/Shared plik _ReservationCalendar.cshtml. Teraz jego zawartość

(listing kodu #1)
Kiedy określiliśmy już zmienne pora stworzyć nagłówek tabeli naszego kalendarza
(listing kodu #2)
Skoro mamy i to przejdźmy do części właściwej czyli pętli, która wygeneruje nam kolejne kratki kalendarza. Dla każdej iteracji stworzymy obiek DateTime dzięki któremu dowiemy się jakim dniem tygodnia jest dany dzień ( lub sprawdzimy czy nie jest zarezerwowany lub cokolwiek innego potrzebujesz ). Rozpoczynając i kończąc strukturę kalendarza uzupełnimy sobie brakujące kratki na podstawie różnicy pomiędzy ilością dni w pełnym tygodniu a numerem dnia pierwszego (na początku) lub ostatniego (na końcu) danego miesiąca.
(listing kodu #3)
I koniec, teraz wystarczy że dodamy następujący wpis na stronie, na której kalendarz ma się pojawić :
(listing kodu #4)
Ten bardzo prosty kawałek kodu pozwala zbudować elastyczny kalendarz, który łatwo zintegrujesz ze swoją stroną w ASP.NET MVC3. Aby rozbudować jego możliwości przede wszystkim trzeba stworzyć odpowiedni ViewModel za pomocą którego przekażesz kolekcję dat do oznaczenia (bądź wykluczenia), wybrany do wyświetlenia miesiąc i rok itd itd. Zysujesz też pełną kontrolę nad wyglądem i zachowaniem kalendarza, wykorzystaniem Ajax – co dla mnie okazało się szybsze i wydajniejsze … ale może pobłądziłem ?

About these ads
Categories: ASP.NET, C#, MVC3, Razor Tags: , , , ,
  1. Judith MCA
    7 July 2011 at 15:27

    Hello! I like your calendar very much!! Any idea of haw to show in the dayOfWeekFirst the last days of the previous month and in the 7 – dayOfWeekLast the first days of the next month???? Thak you!!!!

  2. 31 August 2011 at 11:22

    hey, sorry for the late response, have solved your riddle :-) ?

  1. 17 February 2011 at 16:54
  2. 17 February 2011 at 18:01

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

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: