Second Life of a Hungarian SharePoint Geek

September 9, 2009

How to default calendar item to All day Event?

Filed under: Calendar, Reflection, SharePoint — Tags: , , — Peter Holpar @ 00:43

It was the question in one of the MSDN forum threads.

My first idea was a JavaScript or jQuery included in the NewForm.aspx of the specific Calendar list instance, but this solution would have a few drawbacks. First, it requires you to tamper with one of the form pages of the list using SharePoint Designer – one activity don’t like too much. Second, since the scripts can run only after the page is loaded, and the page is loaded with All Day Event checkbox not selected, and time controls for Start Time and End Time visible, selecting the All Day Event option and hiding the four controls (hours and minutes for both Start Date and End Date) might requires either a postback of the page or more line of script I wish to write now. Third, the script on the customized page should run each time the page is displayed.

My second approach was to modify the default value of the field. The first challange here is that one can not find the All Day Event field in the list of fields when using the „Customize Calendar” page, although the field is there when you check the list of fields in the All Events view.

The All Day Event field is a special out-of-the-box field. When you check the Type property of the „All Day Event” field in a calendar list, it returns AllDayEvent. The class that represents this field is the SPFieldAllDayEvent class, that is inherited from the SPFieldBoolean. The field has no default value defied, as the DefaultValue returns null. When you try to modify this property and call the Update() method of the field, you can see that the it has no effect, the DefaultValue of the field remains null.

It is because this field is „inherited” to the list from the Event content type. You can verify this by attaching the content types of the calendar list (there is only one by default, that is Event), and checking the FieldLinks collection of the Event content type. It includes the All Day Event. Here comes the next problem. The SPFieldLink class has no property that can be used to set the default value. Or maybe it has? Yes, it has, just it is not public.

Here comes reflection into the picture. The property is called Default, it is internal and fortunately has both get and set accessors.

Here is the code one can use to set its value, for example from a command line utility:

 

// Don’t forget this

using System.Reflection;

...

using(SPSite site = 

new SPSite("http://yoursite"))

{

 using(SPWeb web = 

site.OpenWeb())

 {

 SPList list = 

web.Lists["Calendar"];

 SPContentType ct = 

list.ContentTypes["Event"];

 SPFieldLink fieldLink = 

ct.FieldLinks["All Day Event"];

 // Now comes the magic 

🙂

 Type type = typeof(SPFieldLink);

 

PropertyInfo pi = type.GetProperty("Default", BindingFlags.NonPublic | 

BindingFlags.Instance);

 pi.SetValue(fieldLink, "1", 

null);

 ct.Update();

 }

} 

After running the code, you can try to create a new calendar item, and see that now the All Day Event checkbox is selected, and only the date field for the Start Time and End Time fields are visible.

The advantage of this solution is that you should not modify the NewForm.aspx, it must be run only once and the form is loaded every time with the default value already set. The possible drawback is that tampering with the reflection might be not really supported and can have unforeseeable side-effects to your SharePoint installation, so the code above is really only for demonstration purposes, please use that at your own risk.

Finally I should note, that beyond the specific example I discussed above, the method can be used to set list level default values for the site columns.

March 4, 2008

Using Month element in DateRangesOverlap can return items not in the specified month

Filed under: Calendar, CAML, SharePoint — Tags: , , — Peter Holpar @ 23:02

One can logically think that if you set the CalendarDate property of the SPQuery and apply Month as the Value in the DateRangesOverlap element then the query returns items from the month specified in the CalendarDate property.

For example, using the following code …

SPQuery query = new SPQuery();
query.CalendarDate = new DateTime(2008, 3, 1);

… and applying the following CAML query …

<Where>
<DateRangesOverlap>
<FieldRef Name='StartDate' />
<FieldRef Name='EndDate' />
<Value Type='DateTime'>
<Month />
</Value>
</DateRangesOverlap>
</Where>

… one can expect that items having overlap with March 2008 will be only returned.

I’ve found that it is not exactly so, as elements from the end of February and beginning of April may be also returned. The reason for that I think is the simple fact that these items have overlap with the calendar range of the month view of March 2008 (e.g. 24/02/2008-05/04/2008), as the month calendar view includes the full weeks at the beginning and the end of the month, not only the days between 01/03/2008-31/03/2008.

Since DateRangesOverlap is (another) under-documented element of SharePoint and CAML I can’t decide if it is a bug or a feature. Since it is used primarily in the calendar views it seems to be logical that it should return all items that need to be displayed in the month view. So it is probably by design, sad that this fact is not documented.

This fact caused a misbehavior (or let’s call it bug) in one of our custom application, so we should return to our original complex CAML query assembled from Lt, Gt, Leq, Geq, composite And and Or elements…

« Newer Posts

Create a free website or blog at WordPress.com.