Skip to main content

Weblog Ton Stegeman [MVP]

Go Search
Home
  

ODC 2008
If you have a question or suggestion, please contact me through Windows Live Messenger.
My status: .

If I am not online, please send me an e-mail.
Weblog Ton Stegeman [MVP] > Posts > Using SPCalendarView to show items in a calendar
Using SPCalendarView to show items in a calendar

In the new version of the Content By Type webpart, I added the option to rollup items into a calendar. In a later post I will describe how you can do that using the webpart. In this post I will show you how I did it in the code. When you start it all seems very easy, but there were a few things that caused me some headaches. I hope you don't run into them as well after reading this item.

Step 1 - Setting up the controls

I implemented all the calendar specific code in a special control:

public class SharePointCalendar : Control

In the CreateChildControls of my webpart, I just add this control to the collection:

protected override void CreateChildControls()
{
    base.CreateChildControls();
    SharePointCalendar calendar = new SharePointCalendar();
    Controls.Add(calendar);
}

In the CreateChildControls of my SharePointCalendar class, I setup the SPCalendarView and add it to the controls collection:

private SPCalendarView _view;
 
/// <summary>
/// Create the SharePoint calendar. Uses the SharePoint SPCalendarView object.
/// </summary>
protected override void CreateChildControls()
{
    base.CreateChildControls();
    _view = new SPCalendarView();
    _view.EnableViewState = true;
    _view.Width = Unit.Percentage(100);
    _view.DataSource = GetCalendarItems();
    DataBind();
    Controls.Add(_view);
}

You can find SPCalendarView in the Microsoft.SharePoint.WebControls namespace.

Step 2 - Adding data and testing

The data that will be displayed in the calendar is loaded in GetCalendarItems. In this case it is dummy data, but you will get the idea:

private SPCalendarItemCollection GetCalendarItems()
{
    // Create a new collection for the calendar items
    // This is an item with a start and end date.
    SPCalendarItemCollection items = new SPCalendarItemCollection();
 
    // Add the first dummy item
    SPCalendarItem item = new SPCalendarItem();
    item.StartDate = DateTime.Now;
    item.EndDate = DateTime.Now.AddHours(1);
    item.hasEndDate = true;
    item.Title = "First calendar item";
    item.DisplayFormUrl = "/News";
    item.Location = "Utrecht";
    item.Description = "This is the first test item in the calendar rollup";
    item.IsAllDayEvent = false;
    item.IsRecurrence = false;
    item.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);
    items.Add(item);
 
    // Add the second item. This is an all day event.
    SPCalendarItem item2 = new SPCalendarItem();
    item2.StartDate = DateTime.Now.AddDays(-1);
    item.hasEndDate = true;
    item2.Title = "Second calendar item";
    item2.DisplayFormUrl = "/News";
    item2.Location = "Utrecht";
    item2.Description = "This is the second test item in the calendar rollup";
    item2.IsAllDayEvent = true;
    item2.IsRecurrence = false;
    item2.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);
    items.Add(item2);
 
    // return the collection
    return items;
}

If you now build your webpart and add it to a page, it should look like this:

calendar01

Step 3 - The ViewType

Looks nice and it indeed it very simple to do. But now you click one of the links "Week" or "Day" to switch to the daily or weekly view. That doesn't work. The webpart simply does what it does and it shows you the monthly view. If you look at the url however, you will see that the calendar view added a querystring parameter called "CalendarPeriod".

Add the following snippet to the CreateChildControls of the SharePointCalendar to make it work:

if (Page.Request.QueryString["CalendarPeriod"] != null)
{
    switch (Page.Request.QueryString["CalendarPeriod"].ToString().ToLower())
    {
        case "day":
            _view.ViewType = "day";
            break;
        case "week":
            _view.ViewType = "week";
            break;
        case "timeline":
            _view.ViewType = "timeline";
            break;
        default:
            _view.ViewType = "month";
            break;
    }
}

The documentation for the ViewType property shows you the possible values, but please notice that you need to set them in lower case!. Not sure what the option "timeline" does. It looks like a normal monthly view if you use it.

Step 4 - The DisplayFormUrl problem

The property DisplayFormUrl expects are relative url to the item that you added to the calendar. In the sample above, I added a url to the News site. If you look at the properties of the hyperlink, you will see this link:

http://cbt/News?ID=

The calendar view automatically adds a querystring parameter ID to your urls. In this case this is not a problem. In the Content By Type webpart however, I add the same links that are generated by the out of the box ContentQuery webpart. These urls look like this:

http://cbt/_layouts/CopyUtil.aspx?Use=id&Action=dispform&ItemId=1&ListId={70fbb8db-c7b8-4b32-bf77-f61a13b3e0fc}&WebId={087c3dd8-b0a9-4960-9509-da8887d979b6}&SiteId={9fb94730-cc85-4924-957f-7504f415fe0f}

When you add "?ID=" to that url (that is what the calendar view does), your link will not work and the page will display an "Unknown error":

calendar02

In the first approach I tried to fix the urls in javascript, but that didn't work. I was able to trim the "?ID=" bit, but something else kept on adding it back in. I ended up creating a page like the CopyUtil page. When I set the DisplayFormUrl property, I encode the Url that I want to redirect to and add that as a querystring parameter to my redirect page called "tstredirect.aspx":

string link = /_layouts/CopyUtil.aspx?Use=id&Action=dispform&ItemId=1&ListId={70fbb8db-c7b8-4b32-bf77-f61a13b3e0fc}&WebId={087c3dd8-b0a9-4960-9509-da8887d979b6}&SiteId={9fb94730-cc85-4924-957f-7504f415fe0f}
string urlStart = SPContext.Current.Site.ServerRelativeUrl;
if (urlStart == "/")
    urlStart = string.Empty;
link = string.Format("{0}/_layouts/tst/tstredirect.aspx?GoTo={1}", urlStart, System.Web.HttpUtility.UrlEncode(link));
 
item.DisplayFormUrl = link;

In that tstredirect page, I decode the querystring GoTo parameter and redirect to that url.

I am not very happy with that last approach, there should be a better way. If you have a suggestion, please let me know. So after all, it still is pretty easy to use the SPCalendarView in your webparts, if you are aware of these things. In the next post I will show you how I exactly implemented it in the Content By Type webpart.

Comments

Look and feel of calendar

Can ypu please let me know how did u get the look and feel of the SPCalendarView same as the default calendar?
at 1/7/2009 1:39 PM

Look and feel

I did nothing special to get the same look and feel. the SPCalendarView takes care of that.

Ton
Ton Stegeman at 1/12/2009 11:31 PM

Question please

In relation to the line 'In the CreateChildControls of my SharePointCalendar class, I setup the SPCalendarView and add it to the controls collection:'... can you explain to me what you did hear? What this a class inside the main webpart class, or a stand alone class that becomes a control (buecause if it is I am used to seeing the second user control class instantiated by loading it from the file system)... how did you do this? Or could you detail a bith more please.
at 12/4/2009 12:11 PM

Nevermind

I put it together the way it seemed most fit and it worked...

All in one file

using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace SqlDrivenCalendar
{
    [Guid("cf5f3fd5-1776-4c47-9587-4f6fe4f3d645")]
    public class SqlDrivenCalendarWebpart : System.Web.UI.WebControls.WebParts.WebPart
    {
        public SqlDrivenCalendarWebpart(){}

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            SharePointCalendar calendar = new SharePointCalendar();
            Controls.Add(calendar);
        }
    }

    public class SharePointCalendar : Control
    {
        private SPCalendarView _view;

        /// <summary>
        /// Create the SharePoint calendar. Uses the SharePoint SPCalendarView object.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            _view = new SPCalendarView();
            _view.EnableViewState = true;
            _view.Width = Unit.Percentage(100);
            _view.DataSource = GetCalendarItems();
            DataBind();
            Controls.Add(_view);
        }

        private SPCalendarItemCollection GetCalendarItems()
        {
            // Create a new collection for the calendar items
            // This is an item with a start and end date.
            SPCalendarItemCollection items = new SPCalendarItemCollection();

            // Add the first dummy item
            SPCalendarItem item = new SPCalendarItem();
            item.StartDate = DateTime.Now;
            item.EndDate = DateTime.Now.AddHours(1);
            item.hasEndDate = true;
            item.Title = "First calendar item";
            item.DisplayFormUrl = "/News";
            item.Location = "Utrecht";
            item.Description = "This is the first test item in the calendar rollup";
            item.IsAllDayEvent = false;
            item.IsRecurrence = false;
            item.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);
            items.Add(item);

            // Add the second item. This is an all day event.
            SPCalendarItem item2 = new SPCalendarItem();
            item2.StartDate = DateTime.Now.AddDays(-1);
            item.hasEndDate = true;
            item2.Title = "Second calendar item";
            item2.DisplayFormUrl = "/News";
            item2.Location = "Utrecht";
            item2.Description = "This is the second test item in the calendar rollup";
            item2.IsAllDayEvent = true;
            item2.IsRecurrence = false;
            item2.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);
            items.Add(item2);

            // return the collection
            return items;
        }
    }
}
at 12/4/2009 12:57 PM

DisplayFormUrl

string dispFormUrl = string.Format("{0}", oWebsite.ServerRelativeUrl + "/" + oList.Forms[PAGETYPE.PAGE_DISPLAYFORM].Url);
at 12/18/2009 10:15 AM

Add Comment

Items on this list require content approval. Your submission will not appear in public views until approved by someone with proper rights. More information on content approval.

Title


Body *


Your city *


Type the name of the city you live in (making it easier to handle spam...)

CurrentDate *

Select the current date (see if this gives me fewer spam...)
Attachments

 Links

  SharePoint Object on CodePlex
  Screencast introducing SharePoint Objects
  Content by Type and Filter Web Parts on CodePlex
  Archive
  Archive (Calendar)

 My Latest Blog Posts

Scripting SharePoint 2007 setup: choices and conceptsUse SHIFT+ENTER to open the menu (new window).
Adventures in Visual Studio 2010: Migrate the Content By Type web part to SharePoint 2010Use SHIFT+ENTER to open the menu (new window).
Register SharePoint themes by using a featureUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010 development on Windows 2008 Server R2 – Getting StartedUse SHIFT+ENTER to open the menu (new window).
New release SharePoint Objects: features and groupsUse SHIFT+ENTER to open the menu (new window).
Constructing the url to the SharePoint Edit Permissions pageUse SHIFT+ENTER to open the menu (new window).
Screencast: introduction to SharePoint ObjectsUse SHIFT+ENTER to open the menu (new window).
SharePoint 2007 and Reporting ServicesUse SHIFT+ENTER to open the menu (new window).
SharePoint Objects – Insight in usage of your SharePoint artifactsUse SHIFT+ENTER to open the menu (new window).
SharePoint 2007 Custom list schema and the Content Query Web PartUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010 Silverlight Client Object Model – ExecuteQuery vs ExecuteQueryAsyncUse SHIFT+ENTER to open the menu (new window).
SharePoint 2010, the Client Object Models and Bing MapsUse SHIFT+ENTER to open the menu (new window).
Having fun with SharePoint 2010, Silverlight 3 and Bing MapsUse SHIFT+ENTER to open the menu (new window).
Connecting TFS 2010 projects to SharePoint sitesUse SHIFT+ENTER to open the menu (new window).
Adding a database to the SharePoint database Server using SPDatabaseUse SHIFT+ENTER to open the menu (new window).