Hello…
Recently i have been told to display our firm’s time entry in sharepointy calendar view.. First of all it sounded very interesting & still it is
It nearly took me an hour to get a hang of SPCalendarView control provided by ms (thanks to http://www.tonstegeman.com/Blog/Lists/Posts/Post.aspx?ID=60). My main challenge was not to display data out for Sharepoint list, but integrate it with one of our core systems. With SPCalendarView & SPCalendarItem its very easy to display data in a webpart format, but the problem happens, if you intend to use javascript in DisplayFormURL.
It will show you an error :
You must specify a server relative URL at Microsoft.SharePoint.WebControls.SPCalendarItem.set_DisplayFormUrl(String value)
Googled for an hour but with no luck. So i tried to modified the Generated HTML of the Calendar View and hurray it worked!!!. Look at the Render function below which has all the modification. I haven’t use SPCalendarItem’s item.ItemID property, but you can customize it for your purpose.
When the Webpart is getting rendered, i replaced “/replace?ID” with my javascript string. You will also need to replace — ONCLICK=”GoToLink(this);return false; with a blank string. This will prevent displaying the message “Invalid URL”
Look at the status bar in below mentioned images!.


If you had to open a new window (which i had to), when the user clicks on a particular item you can achieve it using the following lines.
//while adding a new item, you can improve the logic here, but this was just for testing.
item.DisplayFormUrl = "/replace/window.open("+ Page.Server.UrlEncode("'") + "item.aspx?time_uno=" + row["id"].ToString();
//when the rendering happens!
StringWriter textWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(textWriter);
calView.RenderControl(htmlWriter);
string replaced = htmlWriter.InnerWriter.ToString();
replaced =Page.Server.UrlDecode(replaced);
replaced = replaced.Replace("/replace/", "javascript:");
replaced = replaced.Replace("?ID=", "');");
replaced = replaced.Replace("ONCLICK=\"GoToLink(this);return false;\" target=\"_self\"", "");
replaced = replaced.Replace("onfocus=\"OnLink(this)\"","");
writer.Write(replaced);
So here it goes
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint.WebControls;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.SharePoint;
using System.Data;
using System.IO;
namespace TimeEntry
{
[Guid("a4e02451-4738-4adf-ab8f-36a27d81c813")]
public class TEViewer : Microsoft.SharePoint.WebPartPages.WebPart
{
/// <summary>
/// Create all your controls here for rendering.
/// Try to avoid using the RenderWebPart() method.
/// </summary>
protected override void CreateChildControls()
{
base.CreateChildControls();
try
{
AddCalendar();
}
catch (Exception ex)
{
Controls.Add(new LiteralControl("<b>Error</b> "));
Controls.Add(new LiteralControl(ex.ToString()));
}
}
private SPCalendarItemCollection GetTimeEntry()
{
SPCalendarItemCollection items = new SPCalendarItemCollection();
Ds = //Your Dataset...
DateTime currentdatetime = DateTime.Now;
foreach (DataRow row in Ds.Tables[0].Rows)
{
SPCalendarItem item = new SPCalendarItem();
//item.ItemID = row["id"].ToString();
item.StartDate = row["StartDate"];
item.EndDate = row["EndDate"];
item.hasEndDate = true;
item.DisplayFormUrl = "/replace";
item.Title = row["Title"]ToString() ;
item.IsAllDayEvent = false;
item.IsRecurrence = false;
item.CalendarType = Convert.ToInt32(SPCalendarType.Gregorian);
items.Add(item);
}
return items;
}
protected override void Render(HtmlTextWriter writer)
{
StringWriter textWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(textWriter);
calView.RenderControl(htmlWriter);
string replaced = htmlWriter.InnerWriter.ToString().Replace("/replace?ID=", "javascript:alert('Sharepoint hacked!');");
replaced = replaced.Replace("ONCLICK="GoToLink(this);return false;"", "");
writer.Write(replaced);
}
SPCalendarView calView;
private void AddCalendar()
{
calView = new SPCalendarView();
calView.ViewType = GetCalendarType(Page.Request["CalendarPeriod"]);
calView.DataSource = GetTimeEntry();
calView.DataBind();
Controls.Add(calView);
}
private static string GetCalendarType(string type)
{
if (type == null)
type = string.Empty;
switch (type.ToLower())
{
case "day":
return "day";
case "week":
return "week";
case "timeline":
return "timeline";
default:
return "month";
}
}
/// <summary>
/// Ensures that the CreateChildControls() is called before events.
/// Use CreateChildControls() to create your controls.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
if (!_error)
{
try
{
base.OnLoad(e);
this.EnsureChildControls();
// Your code here...
}
catch (Exception ex)
{
HandleException(ex);
}
}
}
/// <summary>
/// Clear all child controls and add an error message for display.
/// </summary>
/// <param name="ex"></param>
private void HandleException(Exception ex)
{
this._error = true;
this.Controls.Clear();
this.Controls.Add(new LiteralControl(ex.Message));
}
}
}