Using ASP Calendar Control to Show SharePoint Events

AS many of us know that SharePoint 2007 Calendar does not provide small daily view like date viewer on system data and time page.  So I though why not spend some time on developing small control that can provide this functionality.  So I decided to use ASP.NET Calendar control, CAML and custom code to get his job done.  I actually developed it as Web control.   Please note that I have not done something very complex here it is just a starting point.  You can extend it by the examples that are available on the code project and others.  e.g. using tooltips, AJAX, Silverlight etc if you want.

image

How I did it.

  1. Create a SharePoint Event List
  2. Create Few Events
  3. Create ASP.NET Web Application Project in Visual Studio 2008
  4. Create an Web User Control
  5. Drag ASP.NET Calendar Control to the page and set its properties
  6. Get the Events from Events List using CAML.
  7. Filter and save the events in Arraylist
  8. Implement onDayRender Method of the calendar to set runtime values like holidays and front and background color of the day.
  9. Implement onSelectionChanged Method of the calendar to redirect from current page to day view of Events Calender List view page.
  10. Implement onVisibleMonthchanged method of the calendar to load the event of next month if user change the month.
  11. Deploy the control to ControlTEmplates folder and dll to bin of the current web application
  12. Use Smart Web Part or control container to use this control or if you are using WSS simply make an instance on the page by opening the page in SharePoint Designer.

HTML of Calendar Control

<table cellpadding="0" cellspacing="0" width="100%">
    <tr>
        <td align="center">
            <asp:Calendar ID="calJerry" runat="server" BackColor="White" 
                BorderColor="#3366CC" CellPadding="1" DayNameFormat="Shortest"  
                Font-Names="Verdana" Font-Size="8pt" ForeColor="#003399" Height="200px" 
                Width="100%" BorderWidth="1px" FirstDayOfWeek="Saturday"
                            ondayrender="calJerry_DayRender" 
                            onselectionchanged="calJerry_SelectionChanged" 
                            onvisiblemonthchanged="calJerry_VisibleMonthChanged">
                <SelectedDayStyle BackColor="#009999" Font-Bold="True" ForeColor="#CCFF99" />
                <SelectorStyle BackColor="#99CCCC" ForeColor="#336666" />
                <WeekendDayStyle BackColor="#CCCCFF" />
                <TodayDayStyle BackColor="#33CCCC" ForeColor="Black" />
                <OtherMonthDayStyle ForeColor="#999999" />
                <NextPrevStyle Font-Size="8pt" ForeColor="#CCCCFF" />
                <DayHeaderStyle BackColor="#99CCCC" ForeColor="#336666" Height="1px" />
                <TitleStyle BackColor="#2d3b68" BorderColor="#3366CC" Font-Bold="True" 
                    BorderWidth="1px" Font-Size="10pt" ForeColor="#CCCCFF" Height="25px" />
            </asp:Calendar>
        </td>
    </tr>
</table>

 

CAML to get Events for current Month

string strQuery = "<where><and>" +
               "<Geq><FieldRef Name=\"EventDate\" /><Value Type=\"DateTime\" IncludeTimeValue=\"false\"></Value>" + startDate + "</Geq>" +
               "<Leq><FieldRef Name=\"EndDate\" /><Value Type=\"DateTime\" IncludeTimeValue=\"false\">" + EndDate + "</Value></Leq>" +
                             "</and></where>";

string ViewFields = "<FieldRef Name=\"EventDate\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"EndDate\" />";

This CAML Query will get all the events that are greater or equal than first day of the month and less then equals the last day of the month.

The First and Last days of the months are calculated in the page load.  I got them directly.  You an make them in methods if you want.

Source Code C#

protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                DateTime start = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                DateTime end = start.AddMonths(1).AddDays(-1);

                SaveMonthlyCalenderDates(start.ToString("yyyy/MM/dd"), end.ToString("yyyy/MM/dd"));
            }
        }

SaveMonthlyCalenderDates method will get these events and add them to View state so that I can render them on Day Render method.  After getting the event I will loop on each event and copy it to array list. 

private void SaveMonthlyCalenderDates(string startDate, string EndDate)
        {

            //2009/06/30
            string strQuery = "<where><and>" +
               "<Geq><FieldRef Name=\"EventDate\" /><Value Type=\"DateTime\" IncludeTimeValue=\"false\"></Value>" + startDate + "</Geq>" +
               "<Leq><FieldRef Name=\"EndDate\" /><Value Type=\"DateTime\" IncludeTimeValue=\"false\">" + EndDate + "</Value></Leq>" +
                             "</and></where>";

            string ViewFields = "<FieldRef Name=\"EventDate\" /><FieldRef Name=\"Title\" /><FieldRef Name=\"EndDate\" />";
            SPQuery aQuery = null;
            SPList aList = null;
            ArrayList arrDates = null;
            DataTable dtCalenderEvents = null;
            try
            {
                aQuery = new SPQuery();
                aQuery.Query = strQuery;
                aQuery.ViewFields = ViewFields;
                SPWeb webSite = SPContext.Current.Site.RootWeb;
                aList = webSite.Lists["Calander"];
                dtCalenderEvents = aList.GetItems(aQuery).GetDataTable();
                if (dtCalenderEvents != null)
                {
                    if(dtCalenderEvents.Rows.Count > 0)
                    {
                        arrDates = new ArrayList();
                        foreach (DataRow drEvent in dtCalenderEvents.Rows)
                        {
                            string EventDate = drEvent["EventDate"].ToString();
                            DateTime dtEventDate = Convert.ToDateTime(EventDate);
                            arrDates.Add(dtEventDate.ToString("yyyy/MM/dd"));
                        }
                        ViewState["Calendar"] = arrDates;
                    }
                }
                
            }
            catch (Exception ex)
            {
                string strException = ex.ToString();
            }
            finally
            {
                aQuery = null;
                aList = null;
                dtCalenderEvents = null;
            }

        }

Day Render method is fired each time a day is rendered on the calendar so this is the best place for us to change background of the day that has events.

Note: You can see that I am just checking the start date.  If you want you can also check for Event End Date and change the background if event duration is more than 1 day.  Just depends on your requirements.

You can also see that I have changed to non working days to Thursday and set the background to white on Saturday and Sunday.  This will show that I am in Saudi Arabia.

protected void calJerry_DayRender(object sender, DayRenderEventArgs e)
        {

            DateTime day = e.Day.Date;
            if (day.ToString("dddd") == "Saturday" || day.ToString("dddd") == "Sunday")
            {
                e.Cell.BackColor = System.Drawing.Color.White;
            }

            if (day.ToString("dddd") == "Thursday" || day.ToString("dddd") == "Friday")
            {
                e.Cell.BackColor = System.Drawing.Color.LightBlue;
            }

            if (day.Date == DateTime.Now.Date)
            {
                e.Cell.BackColor = System.Drawing.Color.FromArgb(129, 136, 226);
            }

            if (Cache["Calendar"] != null)
            {
                ArrayList dvDates = ((ArrayList)ViewState["Calendar"]);
                if (dvDates != null)
                {
                    //#12/31/2008#"
                    if(dvDates.Contains(e.Day.Date.ToString("yyyy/MM/dd")))
                    {
                        e.Cell.Attributes.Add("onmouseout", string.Format("title", "Click here to see Event Datails"));
                        e.Cell.BackColor = System.Drawing.Color.Gold;
                        e.Cell.ForeColor = System.Drawing.Color.Black;
                    }

                }
                dvDates = null;
            }
        }

Visible Month Change event is fired when user change the month using the directional images on the calendar so I will call the save monthly calendar dates again which will be rendered again.

protected void calJerry_DayRender(object sender, DayRenderEventArgs e)
        {

            DateTime day = e.Day.Date;
            if (day.ToString("dddd") == "Saturday" || day.ToString("dddd") == "Sunday")
            {
                e.Cell.BackColor = System.Drawing.Color.White;
            }

            if (day.ToString("dddd") == "Thursday" || day.ToString("dddd") == "Friday")
            {
                e.Cell.BackColor = System.Drawing.Color.LightBlue;
            }

            if (day.Date == DateTime.Now.Date)
            {
                e.Cell.BackColor = System.Drawing.Color.FromArgb(129, 136, 226);
            }

            if (Cache["Calendar"] != null)
            {
                ArrayList dvDates = ((ArrayList)ViewState["Calendar"]);
                if (dvDates != null)
                {
                    //#12/31/2008#"
                    if(dvDates.Contains(e.Day.Date.ToString("yyyy/MM/dd")))
                    {
                        e.Cell.Attributes.Add("onmouseout", string.Format("title", "Click here to see Event Datails"));
                        e.Cell.BackColor = System.Drawing.Color.Gold;
                        e.Cell.ForeColor = System.Drawing.Color.Black;
                    }

                }
                dvDates = null;
            }
        

The last method is SelectionChanged method of Calendar which will be fired when a user clicks on any calendar date.  I will get the day month and year of this date and will redirect the user to a page where user can see calendar list view of that day.  I have to format the query string for date and have to add &CalendarPeriod=Day.

protected void calJerry_SelectionChanged(object sender, EventArgs e)
        {
            try
            {
                string strDay = calJerry.SelectedDate.Day.ToString();
                string strMonth = calJerry.SelectedDate.Month.ToString();
                string Year = calJerry.SelectedDate.Year.ToString();

                if (strDay.Trim().Length <= 1)
                {
                    strDay = "0" + strDay;
                }

                if (strMonth.Trim().Length <= 1)
                {
                    strMonth = "0" + strMonth;
                }

                string strSelectedDate = strMonth + "%2F" + strDay +"%2F" + Year;

                string strPortalURL = System.Configuration.ConfigurationManager.AppSettings["PortalURL"].ToString();

                string strURL = strPortalURL + "pages/Calendar.aspx?CalendarDate=" + strSelectedDate + "&CalendarPeriod=Day";
                Response.Redirect(strURL);
            }
            catch (Exception ex)
            {
                //Response.Write(strURL);
            }
            
        }

Summary

I will not put the code for feature and solution here but if you want you can develop a feature/solution to deploy it.  The attached Source Code may not work directly but you can use visual studio to copy paste it to new Control inside your project manually.  I have to do it cause of contractual agreements.

http://cid-a8677d5751e6b4da.skydrive.live.com/embedicon.aspx/Public/calendarcode.zip

 

The source code is available here.  I will try to develop a full fledged visual studio solution for ease of use but can’t promise.  Please feel free to drop an email or comment if you have question.

I hope your guys like it.

4 thoughts on “Using ASP Calendar Control to Show SharePoint Events

  1. thanks for the Custom Calender , can you share full source code to my email . it will be very helpful to implement….Thanks in advance.

Leave a reply to Jerry Yasir Cancel reply