Hi All,
I have looked everywhere and I have not come across a way to highlight multiple dates in a Calendar Extender so I built something myself.
I have put it on here because I know how frustrating it is sometimes when you want to do something but can't!!!
It is a little bit of work but the end results are pretty good.
I am not saying the way that I have done it the “Correct” way but it works!!!
Any way this is what I have done.
The basic premise it that a hidden field on a page is populated with a comma seperated string formatted yyyy-MM-dd and then this is referenced in a Javascript.
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="asp" %><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><title></title></head><body><form id="form1" runat="server"><div><asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager><script src="Scripts/HighlightCalendar.js" type="text/javascript"></script><asp:TextBox ID="txb_Date" runat="server"></asp:TextBox><asp:CalendarExtender ID="txb_Date_CalendarExtender" runat="server" Enabled="True" OnClientShown="HighlightDates" Format="dd/MM/yyyy" TargetControlID="txb_Date" BehaviorID="jtxb_Date_CalendarExtender"></asp:CalendarExtender><asp:HiddenField ID="hf_Dates" runat="server" /></div></form></body></html>
The code behind looks like this (just replace the connection string and query to suit):
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data; using System.Data.SqlClient; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { DataSet ds = new DataSet(); string connStr = "Data Source=SQL-DW1;Initial Catalog=Vehicles;Integrated Security=true;Connection Timeout=60"; SqlConnection sqlConn = new SqlConnection(connStr); SqlCommand sqlCmd = new SqlCommand(); sqlCmd.CommandType = CommandType.Text; sqlCmd.CommandText = "SELECT DISTINCT PurchaseDate FROM vRegHistory"; sqlCmd.CommandTimeout = 300; sqlCmd.Connection = sqlConn; sqlConn.Open(); SqlDataAdapter da = new SqlDataAdapter(sqlCmd); da.Fill(ds, "PurchaseDates"); sqlConn.Close(); da.Dispose(); DataTable dt = ds.Tables["PurchaseDates"]; string CommaSepDates = ""; if (dt.Rows.Count > 0) { foreach (DataRow dr in dt.Rows) { DateTime PurchaseDate = DateTime.Parse(dr["PurchaseDate"].ToString()); CommaSepDates = CommaSepDates + PurchaseDate.ToString("yyyy-MM-dd") + ","; } hf_Dates.Value = CommaSepDates.Substring(0, CommaSepDates.Length - 1); } } } }
When the Calendar is shown it scans each of the calendar screens and for each row and cell it will check if the tool tip or the text inside matches one of the dates. If so then it will highlight the cell.
In a folder called "Scripts" create a Javascript file called "HighlightCalendar" and paste the below into it.
//Main function called when the Calendar is shown function HighlightDates() { var cal = $find("jtxb_Date_CalendarExtender"); if (cal != null) { //Add handlers to the Arrows and the table header so that if these are used then it rescans the calendar. Otherwise the Cells retain the coloring addMyHandler(cal._prevArrow); addMyHandler(cal._nextArrow); addMyHandler(cal._header); //Start the initial scan processDates(); } } //This is the secondary function that is called while the calendar is open when any of the cells are clicked function processDates() { var cal = $find("jtxb_Date_CalendarExtender"); if (cal != null) { //Scan each of the Calendar screens passing throught the date format to look for ColourCells(cal._daysBody, "dddd, MMMM dd, yyyy", cal._mode); ColourCells(cal._monthsBody, "MMMM, yyyy", cal._mode); ColourCells(cal._yearsBody, "<BR>yyyy", cal._mode); } } //This returns a string with all of the dates formatted function formatDates(dateFormat) { var formattedDates = "dates"; var hf_PurchaseDates = document.getElementById("hf_Dates"); //Split the comma seperated dates into an array var dateArray = hf_PurchaseDates.value.split(','); //loop through the date array and return a formatted date for (a in dateArray) { //Split the date into an array var myYMD = dateArray[a].toString().split("-"); //Get the year month and day (if you want to change the date format then you will need to change these around var myYear = parseInt(myYMD[0].toString(), 10); var myMonth = parseInt(myYMD[1].toString(), 10) - 1; var myDay = parseInt(myYMD[2].toString(), 10); //Get the formatted date var myDate = new Date(myYear, myMonth, myDay).format(dateFormat); //Only add new formatted dates to the return string if (formattedDates.indexOf(myDate) == -1) { formattedDates = formattedDates + "," + myDate; } } return formattedDates; } //This is the function that scans the Calendar screen function ColourCells(obj, dateFormat, calMode) { var formattedDates = formatDates(dateFormat); //Loop through each of the Rows for (var i = 0; i < obj.rows.length; i++) { //Loop through each of the cells for (var j = 0; j < obj.rows[i].cells.length; j++) { var cell = obj.rows[i].cells[j]; var match = 0; //If the Screen is years then there is no Tool tip so you have to use the text in the cell and this includes the html <BR> tag //other wise use the tooltip if ((calMode == "years" && formattedDates.indexOf(cell.firstChild.innerHTML) > -1) || (calMode != "years" && formattedDates.indexOf(cell.firstChild.title) > -1)) { cell.style.backgroundColor = "Silver"; cell.style.color = "White"; match++; } else { cell.style.backgroundColor = "White"; cell.style.color = "Black"; } //Add the handler to the cell addMyHandler(cell.firstChild); } } } //Add a handler so that it rescans function addMyHandler(i) { //delete it if it is all ready there try { Sys.UI.DomEvent.removeHandler(i, "blur", processDates); } catch (exception) { } Sys.UI.DomEvent.addHandler(i, "blur", processDates); }
Hope this helps :)
Hayden