Thursday, April 9, 2009

Customising the SharePoint Calendar

A few days ago I came across a great post by syed.er's blog called Bending SharePoint without bending the rules. In November he talked about adding more items to the calendar view by adding MaxvisibleEvents to the Rendering Template for the Calendar. I decided to take that concept a level further.

Following problem scenario:
We need to be able to colour code calendar entries, add more than just the title to the item and break down the multi day events into separate blocks spanning across the whole day and not just a thin bar at the top which is easily skipped. All this without changing the insides of SharePoint. And the solution could not be simpler!

First of all you will need to create your own WebPart for the calendar. Sound daunting? not at all! you can easily implement the SPCalendarView control to do all the work for you.
Gunnar Peipmann has a great post on how to create a global calendar from multiple sources using the SPCalendarView.

The SpCalendarView control can also accept new Templates. So you copy the Rendering Templates for the Calendar Control from the C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES \defaulttemplates.ascx into a new ascx file, rename them and add the fields you want to the Item views. Then hook them up programatically with the SPCalendarView control and render the new output.

WARNING! Don't put the custom Rendering Templates into a subfolder. Although it might make perfect sense, they won't load properly programatically. Just use clear and concise naming conventions for your custom ascx page. Then use the SPControlTemplateManager.GetTemplateByName() function to get hold of the ITemplate programatically and plonk it into the Calendar View.
If you insist on having the custom template in a subfolder, check out Reverse Alchemy's post on loading templates programatically. He will show you how to use Page.LoadControl() as a workaround to SharePoint misbehaving.

You will need to populate the list of events manually though. I.e. use a SPQuery to get the events in a collection, iterate through the collection and create new Calendar Entries based on the list item. But Gunnar's blog will guide you through that. While you're recreating the calendar entries try changing the Backgroundcss attribute of the entry. :-) and voilla you have a colour coded calendar that has all the functionality of the normal calendar.
Ok. Maybe it is not quite as easy. I'll upload a step by step instruction sometime after easter if enough people pester me about it...

10 comments:

William said...

I'm very curious as to how you broke up the multi-day events and put them in separate blocks. You mentioned it, but never really eluded to how you did it. Can you elaborate on that please?

alx said...

The trick is simple. Now that you have full control over what events go in the calendar you create multiple events for the same list item and make sure that each event runs over one day only. I.e. an event from 09:30 Monday to 17:00 Wednesday becomes three separate events. 09:30-23:00, 01:00-23:00 and 01:00-17:00

Bret Mix said...

I've got an unusual project I'm working on at the moment, and am wondering if your tip may apply... My manager is needing an hourly calendar that runs left-to-right (hours across the top) instead of up-and-down (hours on the left side), sort of like an hourly Gantt chart.

Does the template itself have enough control over the calendar to allow a modification like this? (Great post, BTW.)

alx said...

Hmm sounds like fun. From the top of my head... I think you will get lucky. The templates are extensive and you should be able to get what you want. my advice, delete all html markup from the copy of the rendering templates, leaving the template calls in place and rebuild from scratch. Just beware, there are quite a few templates that come together to build a calendar.

Bret Mix said...

Thanks for the response! I was away from work for a couple of days, and only today got to dig back into it. I'm taking your advice and digging into the calendar templates now (as you well know, there is a LOT of stuff in there).

I think the templates may be the key to the whole thing (along with some javascript, I think). I'm really just starting out, I'll post back if I make some kind of earth-shattering discovery. Thanks again for the help.

MAT said...

Thanks for sharing this.
Great info!

Chetan said...

What approach would you suggest if I wanted to build a View for a Yearly Calendar. I don't see any Javascript functions Like "YearView()" in core.js either. Thanks.

alx said...

Now that is a fun one. Having a calendar that shows a whole year instead of a day, week or month.
As you will need to figure out the dataset for the view yourself you won't have much fun with rendering templates.
As the asp.net calendar control also is not designed for year views you will have no other option but to create your own custom WebPart which reads out the calendar entries using the API and populates your custom control which uses your own custom rendering.
You can also try to do it using a usercontrol and then loading the uc using Loadcontrol into a WebPart. That is often faster as you can split the design from the code.

Northstop said...

Is there an elegant method to have only a five day work week calendar and not show Sat/Sun?

Ideally without a new webpart or internal coding? The developers HATE when I ask using the dreaded "customization" word.

alx said...

Northstop, I understand why you shy away from that word, but maybe using another one instead would make you feel better. Remember, SharePoint is a fFramework. It was always meant to be used and extended.
I particularly like the way Mark Orange puts it:
There are three ways of getting the most out of SharePoint: Configuring it, Extending it, Customising it.
Two of them are good, one is bad... Configuration will only get you so far. Yes, there are loads of configuraitons that can be done, but at some point you'll hit a brick wall. That's where extending the Framework comes in. The microsoft developers have given us the ability to create custom templates for the OOB controls. They want us to customise it! But the magic trick is to stick to the Framework. Use WSP packages to deploy changes. Never overwrite files directly in the 12 hive and use the customisation techniques which have been designed just for that purpose. To extend SharePoint.
Only when you break the rules and start hacking with the framweork itself are you falling for the "dark side" and will end up creating monstrosities which are not upgradeable, maintainable or stable.
So don'y ask your developers to customise SharePoint. Ask them to extend it!!!

And to the elegant approach to your issue? Three options I can think of.
1) (my favourite) create a custom Rendering Template for your calendar and create a WebPart that uses the SPCalendarView Control with the custom rendering template applied
2) Create a custom calendar webpart from scratch.
3) Create a funky silverlight webpart that uses the Events List as its datasource.

Obviously there are more ways to achieve what you are looking for, but I'd always go with the option that utilises most OOB functionality.