Michael Schau

My SharePoint Blog

SPCalendarView - order of SPCalendarItems

When adding SPCalendarItems to the SPCalendarItemCollection you need to be carefull about in which order you add them. If SPCalendarItems are added in a specific order, they doesn’t show in Month view.
In the example below Test User 1 doesn’t show in the week starting Septemper 21st. In this week the calendar item for Test User 2 is added to the collection after Test User 1.
If the items are added in reverse order as they are in the week starting September 14th, both items are visible in Month view as expected.

If you however switch to Week view Test User 1 is visible. It is also visible in Day view.
So it's not because it doesn't exist in the collection, it just doesn't show in Month view.

Here's some code to reproduce the issue.

private DataTable GetHolidayData()
{
    DataTable holidayData = new DataTable("HolidayData");
    holidayData.Columns.Add("ID", Type.GetType("System.String"));
    holidayData.Columns.Add("Organizer", Type.GetType("System.String"));
    holidayData.Columns.Add("FromDate", Type.GetType("System.DateTime"));
    holidayData.Columns.Add("ToDate", Type.GetType("System.DateTime"));
    holidayData.Columns.Add("IsAllDayEvent", Type.GetType("System.Boolean"));

    DataRow row = holidayData.NewRow();

    row[0] = "test1@test.com";
    row[1] = "Test User 1";
    row[2] = "2009/09/23";
    row[3] = "2009/09/25";
    row[4] = true;

    holidayData.Rows.Add(row);

    DataRow row2 = holidayData.NewRow();

    row2[0] = "test2@test.com";
    row2[1] = "Test User 2";
    row2[2] = "2009/09/21";
    row2[3] = "2009/09/25";
    row2[4] = true;

    holidayData.Rows.Add(row2);
    // row2 will not show in month view

    DataRow row3 = holidayData.NewRow();

    row3[0] = "test2@test.com";
    row3[1] = "Test User 2";
    row3[2] = "2009/09/14";
    row3[3] = "2009/09/18";
    row3[4] = true;

    holidayData.Rows.Add(row3);

    DataRow row4 = holidayData.NewRow();

    row4[0] = "test1@test.com";
    row4[1] = "Test User 1";
    row4[2] = "2009/09/16";
    row4[3] = "2009/09/18";
    row4[4] = true;

    holidayData.Rows.Add(row4);
    // adding a calendar item with a shorter duration last, 
    // will make it visible in month view.

    return holidayData;
}

private SPCalendarItemCollection GetCalendarItems(DataTable results)
{
    SPCalendarItemCollection items = new SPCalendarItemCollection();
    using (SPWeb web = SPContext.Current.Web)
    {
        foreach (DataRow row in results.Rows)
        {
            SPCalendarItem item = new SPCalendarItem();

            item.Title = row["Organizer"] as string;
            item.StartDate = (System.DateTime)row["FromDate"];
            item.EndDate = (System.DateTime)row["ToDate"];
            item.hasEndDate = true;
            item.IsAllDayEvent = (System.Boolean)row["IsAllDayEvent"];
            item.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);

            items.Add(item);
        }
    }

    return items;            
}

So how do we workaround it? As mentioned in the beginning it depends on the order of items.
Sorting on FromDate ascending will make all items visible in Month view. In my sample code above we can easily sort using a DataView.

    DataView v = results.DefaultView;
    v.Sort = "FromDate ASC";
    results = v.ToTable();