[Mono-bugs] [Bug 74718][Nor] New - Data Bound Control inherited from Calendar does not render Day on Days with Data Bound items

bugzilla-daemon@bugzilla.ximian.com bugzilla-daemon@bugzilla.ximian.com
Sun, 24 Apr 2005 18:57:41 -0400 (EDT)


Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.

Changed by joe_audette@yahoo.com.

http://bugzilla.ximian.com/show_bug.cgi?id=74718

--- shadow/74718	2005-04-24 18:57:41.000000000 -0400
+++ shadow/74718.tmp.22678	2005-04-24 18:57:41.000000000 -0400
@@ -0,0 +1,470 @@
+Bug#: 74718
+Product: Mono: Tools
+Version: 1.1
+OS: SUSE 9.2
+OS Details: 
+Status: NEW   
+Resolution: 
+Severity: 
+Priority: Normal
+Component: XSP
+AssignedTo: gonzalo@ximian.com                            
+ReportedBy: joe_audette@yahoo.com               
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL: 
+Cc: 
+Summary: Data Bound Control inherited from Calendar does not render Day on Days with Data Bound items
+
+Please fill in this template when reporting a bug, unless you know what 
+you are doing.
+
+Description of Problem:
+I am trying to use a Data bound control that inherits from the 
+System.Web.UI.WebControls.Calendar and INamingContainer. It works as 
+expected on Windows but under mono the Day number is not rendering on days 
+with data bound items. The Day number should be clickable to select the 
+day. I am attaching a page with inline code and 2 classes that need to be 
+compiled into DataCalendar.dll. Please tell me if you see something I can 
+do to make it work in both places by changing my code.
+
+I am running Suse 9.2 with mono 1.1.7 r43477 from svn
+I am using mod_mono with Apache
+
+
+Steps to reproduce the problem:
+1. Compile the 2 classes DataCalendar and DataCalendarItem into 
+DataCalendar.dll
+2. Try the attached page with the DataCalendar.dll accessible to it in the 
+bin folder
+
+
+Actual Results:
+The Day number does not render in the calendar for days with data bound 
+items.
+
+
+Expected Results:
+The Day number does render and is clickable for postback. This is the 
+behaviour on Windows.
+
+
+How often does this happen? 
+Every Time
+
+Additional Information:
+Page Code Starts here
+-----------------------
+<% @Register Namespace="DataControls" Assembly="DataCalendar" 
+TagPrefix="dc" %>
+
+<% @Import Namespace="System.Data" %>
+
+<script language="cs" runat="server">
+
+    DataTable GetEventData()
+    {
+        DataTable dt = new DataTable();
+        
+        dt.Columns.Add("EventTitle", typeof(String));
+        dt.Columns.Add("EventDay", typeof(DateTime));
+        dt.Columns.Add("Color", typeof(System.Drawing.Color));
+        
+        DataRow r = dt.NewRow();
+        r["EventTitle"] = "Today's Event";
+        r["EventDay"] = System.DateTime.Today;
+        r["Color"] = System.Drawing.Color.Black;
+        dt.Rows.Add(r);
+
+        r = dt.NewRow();
+        r["EventTitle"] = "Tomorrow's Event";
+        r["EventDay"] = System.DateTime.Today.AddDays(1);
+        r["Color"] = System.Drawing.Color.Red;
+        dt.Rows.Add(r);
+
+        r = dt.NewRow();
+        r["EventTitle"] = "Tomorrow's Event #2";
+        r["EventDay"] = System.DateTime.Today.AddDays(1);
+        r["Color"] = System.Drawing.Color.Blue;
+        dt.Rows.Add(r);
+
+        r = dt.NewRow();
+        r["EventTitle"] = "Next Week's Event";
+        r["EventDay"] = System.DateTime.Today.AddDays(7);
+        r["Color"] = System.Drawing.Color.Green;
+        dt.Rows.Add(r);
+
+        return dt;
+    }
+    
+
+    void Page_Load(Object o, EventArgs e)
+    {
+        cal1.DataSource = GetEventData();
+    }
+    
+</script>
+
+
+<html>
+    <head><title>DataCalendar - Example 1</title></head>
+    
+    <body>
+        <form runat="server">
+                    
+            <h3>Events DataTable constructed through code</h3>
+            
+            <dc:DataCalendar id="cal1" runat="server" width="100%"  
+DayField="EventDay"
+                             BorderWidth="1" BorderStyle="None" 
+CellPadding="0"
+			     	SelectorStyle-BorderWidth="0"  Font-
+Name="Tahoma" SelectionMode="Day" ShowGridLines="True"
+			     	 TitleStyle-CssClass="EventCalendarTitle"
+			     	TitleStyle-BorderWidth="0" DayHeaderStyle-
+CssClass="EventCalendarDayHeader" DayStyle-CssClass="EventCalendarDay"
+			     	WeekendDayStyle-
+CssClass="EventCalendarWeekendDay" 
+			     	NextPrevStyle-
+CssClass="EventCalendarNextPrev" NextPrevStyle-ForeColor="White">
+			     	<DayWithEventsStyle ForeColor="#0033ff" 
+Font-Bold="True" />
+			     	<CurrentDayStyle BackColor="WhiteSmoke" 
+ForeColor="DarkGray" Font-Bold="True" />
+					<OtherMonthDayStyle 
+BackColor="LightGray" ForeColor="DarkGray" />
+	
+                <ItemTemplate>
+                    <br />
+                    <asp:Label id="lblTitle" runat="server"
+                               Font-Size="8"
+                               Font-Name="Arial" 
+                               Text='<%# Container.DataItem["EventTitle"] %
+>'
+                               ForeColor='<%# Container.DataItem["Color"] %
+>'
+                            />
+                            
+                </ItemTemplate>
+            </dc:DataCalendar>
+            
+        </form>
+    </body>
+        
+</html>
+
+---- End Page Code------
+
+//Compile the 2 classes below into DataCalendar.dll and put in the bin 
+where the above page can find it.
+
+using System;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+using System.Data;
+
+namespace DataControls
+{    
+
+	/********************************************************
+	  Class DataCalendarItem
+		- serves as the container for a single calendar entry,
+		  allowing for databinding syntax like the following
+		  to be used in the .aspx page:
+          
+			<%# Container.DataItem("MyField") %>            
+	 ********************************************************/
+
+	public class DataCalendarItem : Control, INamingContainer
+	{
+
+		private DataRow _dataItem;
+
+		public DataCalendarItem(DataRow dr) 
+		{
+			_dataItem = dr;
+		}
+
+		// because the source data will be a DataTable
+		// object, it makes sense for our DataItem
+		// property to return a DataRow object
+		// (i.e. a single item in the data source
+		//  corresponds to a single row of data)
+		public DataRow DataItem 
+		{
+			get {return _dataItem;}
+			set {_dataItem = value;}
+		}
+	}
+
+
+	/********************************************************
+	  Class DataCalendar
+		- subclass of the ASP.NET Calendar control for
+		  displaying events from a DataTable with support
+		  for templates
+	 ********************************************************/
+
+	public class DataCalendar : Calendar, INamingContainer
+	{
+        
+		private object _dataSource;
+		private string _dataMember;
+		private string _dayField;
+		private ITemplate _itemTemplate;
+		private ITemplate _noEventsTemplate;
+		private TableItemStyle _dayWithEventsStyle = new 
+TableItemStyle();
+		private TableItemStyle _currentDayStyle = new 
+TableItemStyle();
+		private DataTable _dtSource;
+        
+		// Support either a DataSet or DataTable object
+		// for the DataSource property
+		public object DataSource 
+		{
+			get {return _dataSource;}
+			set 
+			{
+				if (value is DataTable || value is 
+DataSet) 
+					_dataSource = value;
+				else
+					throw new Exception("The 
+DataSource property of the DataCalendar control" +
+						" must be a DataTable or 
+DataSet object");
+			}
+		}
+        
+		// If a DataSet is supplied for DataSource,
+		// use this property to determine which
+		// DataTable within the DataSet should
+		// be used; if DataMember is not supplied,
+		// the first table in the DataSet will
+		// be used.
+		public string DataMember 
+		{
+			get {return _dataMember;}
+			set {_dataMember = value;}
+		}
+        
+        
+		// Specify the name of the field within
+		// the source DataTable that contains
+		// a DateTime value for displaying in the
+		// calendar.
+		public string DayField 
+		{
+			get {return _dayField;}
+			set {_dayField = value;}
+		}
+
+
+
+		public TableItemStyle DayWithEventsStyle 
+		{
+			get {return _dayWithEventsStyle;}
+			set {_dayWithEventsStyle = value;}
+		}
+
+		public TableItemStyle CurrentDayStyle 
+		{
+			get {return _currentDayStyle;}
+			set {_currentDayStyle = value;}
+		}
+
+		[TemplateContainer(typeof(DataCalendarItem))]    
+		public ITemplate ItemTemplate
+		{
+			get {return _itemTemplate; }
+			set {_itemTemplate = value;}
+		}
+
+
+		[TemplateContainer(typeof(DataCalendarItem))]    
+		public ITemplate NoEventsTemplate
+		{
+			get {return _noEventsTemplate; }
+			set {_noEventsTemplate = value;}
+		}
+
+		//		[TemplateContainer(typeof
+(DataCalendarItem))]    
+		//		public ITemplate SelectedDayTemplate
+		//		{
+		//			get {return _selectedDayTemplate; }
+		//			set {_selectedDayTemplate = value;}
+		//		}
+
+
+		// Constructor    
+		public DataCalendar() : base() 
+		{
+			// since this control will be used for displaying
+			// events, set these properties as a default
+			this.SelectionMode = CalendarSelectionMode.None;
+			this.ShowGridLines = true;
+		}
+        
+        
+		private void SetupCalendarItem(TableCell cell, DataRow r, 
+ITemplate t) 
+		{
+			// given a calendar cell and a datarow, set up the
+			// templated item and resolve data binding syntax
+			// in the template
+			DataCalendarItem dti = new DataCalendarItem(r);
+			t.InstantiateIn(dti);
+			dti.DataBind();
+			cell.Controls.Add(dti);            
+		}
+        
+        
+		protected override void OnDayRender(TableCell cell, 
+CalendarDay day)
+		{
+			// _dtSource was already set by the Render 
+method            
+			if (_dtSource != null) 
+			{
+                
+				// We have the data source as a DataTable 
+now;                
+				// filter the records in the DataTable for 
+the given day;
+				// force the date format to be MM/dd/yyyy
+				// to ensure compatibility with RowFilter
+				// date expression syntax (#date#).
+				// Also, take the possibility of time
+				// values into account by specifying
+				// a date range, to include the full day
+				DataView dv = new DataView(_dtSource);
+				dv.RowFilter = string.Format(
+					"{0} >= #{1}# and {0} < #{2}#", 
+					this.DayField, 
+					day.Date.ToString("MM/dd/yyyy"), 
+					day.Date.AddDays(1).ToString
+("MM/dd/yyyy")
+					);
+
+                                
+				// are there events on this day?
+				if (dv.Count > 0) 
+				{
+					// there are events on this day; 
+if indicated, 
+					// apply the DayWithEventsStyle to 
+the table cell
+					if(day.Date == this.SelectedDate)
+					{
+						if (this._currentDayStyle !
+= null) 
+						{
+						
+							cell.ApplyStyle
+(this._currentDayStyle);
+						}
+
+					}
+					else
+					{
+						if 
+(this.DayWithEventsStyle != null) 
+							cell.ApplyStyle
+(this.DayWithEventsStyle);
+					}
+                    
+					// for each event on this day 
+apply the
+					// ItemTemplate, with data bound 
+to the item's row
+					// from the data source
+					if (this.ItemTemplate != null)
+						for (int i=0; i<dv.Count; 
+i++) 
+						{
+							SetupCalendarItem
+(cell, dv[i].Row, this.ItemTemplate);
+						}              
+
+				} 
+				else 
+				{
+					// no events this day;
+					if(day.Date == this.SelectedDate)
+					{
+						if (this._currentDayStyle !
+= null) 
+						{
+							
+							cell.ApplyStyle
+(this._currentDayStyle);
+						}
+					}
+					else
+					{
+						if (this.NoEventsTemplate !
+= null)
+							SetupCalendarItem
+(cell, null, this.NoEventsTemplate);
+					}
+                        
+				}                
+                  
+			}            
+            
+			// call the base render method too
+
+			//  Joe Audette Note: Commenting this out does not 
+change the behaviour under windows
+			// it still works as expected
+			base.OnDayRender(cell, day);
+            
+		}                
+        
+		protected override void Render(HtmlTextWriter html)
+		{
+			_dtSource = null;
+
+			if (this.DataSource != null && this.DayField != 
+null) 
+			{
+				// determine if the datasource is a 
+DataSet or DataTable
+				if (this.DataSource is DataTable) 
+					_dtSource = (DataTable) 
+this.DataSource;                
+				if (this.DataSource is DataSet)
+				{
+					DataSet ds = (DataSet) 
+this.DataSource;
+					if (this.DataMember == null || 
+this.DataMember == "")
+						// if data member isn't 
+supplied, default to the first table
+						_dtSource = ds.Tables[0];
+					else
+						// if data member is 
+supplied, use it
+						_dtSource = ds.Tables
+[this.DataMember];                        
+				}
+				// throw an exception if there is a 
+problem with the data source
+				if (_dtSource == null)
+					throw new Exception("Error finding 
+the DataSource.  Please check " +
+						" the DataSource and 
+DataMember properties.");
+			}                    
+
+			// call the base Calendar's Render method
+			// allowing OnDayRender() to be executed
+			base.Render(html);
+		}
+           
+    
+	}
+    
+}