Windows Develop Bookmark and Share   
 index > Windows Forms Designer > DataGridView Calender Column
 

DataGridView Calender Column

Hi,

Language used: C# (Visual Studio 2005 Pro)

I am using this articlefrom Microsoft to add a calendar feature to my DataGridView. I got it working in a few minutes but would like to know how to get around a few problems.

1: My DataGridView allows the user to add rows. When the first row prompt comes up (a blank new row), it already sets the two calendar columns I have to a default date of DateTime.Now. I want to be able to stop that. I cannot initialize the DataGridView to NULL these cells as this causes the calendar class (from the forementioned article to crash).

2: When the user starts inserting data into the first row and the second row pops open automatically, it populates this row also with the default date of DateTime.Now. I also need to be able to stop that from happening.

3: I only want to open the calendar and record the date from the cell if the user clicked within the cell to input a date in the first place. How can I make it do that? Some of my cells will remain NULL and the user won't input a date if the master date from another part of the program is desired.

Many thanks in advance for any replies!

Sean
Sean Connolly  Wednesday, August 05, 2009 10:05 AM
Hi,

I think I found a way by modifying the code to the following:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace MyProgram
{
	class CalendarCells
	{
		public class CalendarColumn : DataGridViewColumn
		{
			public CalendarColumn() : base(new CalendarCell())
			{
			}

			public override DataGridViewCell CellTemplate
			{
				get
				{
					return base.CellTemplate;
				}
				set
				{
					// Ensure that the cell used for the template is a CalendarCell.
					if (value != null && 
						!value.GetType().IsAssignableFrom(typeof(CalendarCell)))
					{
						throw new InvalidCastException("Must be a CalendarCell");
					}
					base.CellTemplate = value;
				}
			}
		}

		public class CalendarCell : DataGridViewTextBoxCell
		{

			public CalendarCell()
				: base()
			{
				// Use the short date format.
				this.Style.Format = "d";
			}

			public override void InitializeEditingControl(int rowIndex, object 
				initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
			{
				// Set the value of the editing control to the current cell value.
				base.InitializeEditingControl(rowIndex, initialFormattedValue, 
					dataGridViewCellStyle);
				CalendarEditingControl ctl = 
					DataGridView.EditingControl as CalendarEditingControl;
				try
				{
					ctl.Value = (DateTime)this.Value;
				}
				catch
				{
					ctl.Value = DateTime.Now;
				}
			}

			public override Type EditType
			{
				get
				{
					// Return the type of the editing contol that CalendarCell uses.
					return typeof(CalendarEditingControl);
				}
			}

			public override Type ValueType
			{
				get
				{
					// Return the type of the value that CalendarCell contains.
					return typeof(DateTime);
				}
			}

			public override object DefaultNewRowValue
			{
				get
				{
					// Use the current date and time as the default value.
					//return DateTime.Now;
					return null;
				}
			}
		}

		class CalendarEditingControl : DateTimePicker, IDataGridViewEditingControl
		{
			DataGridView dataGridView;
			private bool valueChanged = false;
			int rowIndex;

			public CalendarEditingControl()
			{
				this.Format = DateTimePickerFormat.Short;
			}

			// Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
			// property.
			public object EditingControlFormattedValue
			{
				get
				{
					return this.Value.ToShortDateString();
				}
				set
				{
					if (value is String)
					{
						this.Value = DateTime.Parse((String)value);
					}
				}
			}

			// Implements the 
			// IDataGridViewEditingControl.GetEditingControlFormattedValue method.
			public object GetEditingControlFormattedValue(
				DataGridViewDataErrorContexts context)
			{
				return EditingControlFormattedValue;
			}

			// Implements the 
			// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
			public void ApplyCellStyleToEditingControl(
				DataGridViewCellStyle dataGridViewCellStyle)
			{
				this.Font = dataGridViewCellStyle.Font;
				this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
				this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
			}

			// Implements the IDataGridViewEditingControl.EditingControlRowIndex 
			// property.
			public int EditingControlRowIndex
			{
				get
				{
					return rowIndex;
				}
				set
				{
					rowIndex = value;
				}
			}

			// Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
			// method.
			public bool EditingControlWantsInputKey(
				Keys key, bool dataGridViewWantsInputKey)
			{
				// Let the DateTimePicker handle the keys listed.
				switch (key & Keys.KeyCode)
				{
					case Keys.Left:
					case Keys.Up:
					case Keys.Down:
					case Keys.Right:
					case Keys.Home:
					case Keys.End:
					case Keys.PageDown:
					case Keys.PageUp:
						return true;
					default:
						return !dataGridViewWantsInputKey;
				}
			}

			// Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
			// method.
			public void PrepareEditingControlForEdit(bool selectAll)
			{
				// No preparation needs to be done.
			}

			// Implements the IDataGridViewEditingControl
			// .RepositionEditingControlOnValueChange property.
			public bool RepositionEditingControlOnValueChange
			{
				get
				{
					return false;
				}
			}

			// Implements the IDataGridViewEditingControl
			// .EditingControlDataGridView property.
			public DataGridView EditingControlDataGridView
			{
				get
				{
					return dataGridView;
				}
				set
				{
					dataGridView = value;
				}
			}

			// Implements the IDataGridViewEditingControl
			// .EditingControlValueChanged property.
			public bool EditingControlValueChanged
			{
				get
				{
					return valueChanged;
				}
				set
				{
					valueChanged = value;
				}
			}

			// Implements the IDataGridViewEditingControl
			// .EditingPanelCursor property.
			public Cursor EditingPanelCursor
			{
				get
				{
					return base.Cursor;
				}
			}

			protected override void OnValueChanged(EventArgs eventargs)
			{
				// Notify the DataGridView that the contents of the cell
				// have changed.
				valueChanged = true;
				this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
				base.OnValueChanged(eventargs);
			}
		}
	}
}
To get blank cells on the calendar, all I have done is in the public override object DefaultNewRowValue function is to remove the return value and return NULL instead (I've commented it out and left it in for reference).

I also modified the InitializeEditingControl function to put a try/catch around the part which reads the value from the cell when initializing the calendar cell. If the TRY picks up a NULL, the code falls through to the CATCH statement which just uses DateTime.Now to initialize the calendar which is acceptable! If I decide I am editing the wrong cell, the ESCAPE key still reverts to a blank cell which is great!

Thanks for looking into this, I will see how I go with this one. Hopefully it may help someone else!

Sean
Sean Connolly  Wednesday, August 05, 2009 11:40 AM
Hi,

I think I found a way by modifying the code to the following:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace MyProgram
{
	class CalendarCells
	{
		public class CalendarColumn : DataGridViewColumn
		{
			public CalendarColumn() : base(new CalendarCell())
			{
			}

			public override DataGridViewCell CellTemplate
			{
				get
				{
					return base.CellTemplate;
				}
				set
				{
					// Ensure that the cell used for the template is a CalendarCell.
					if (value != null && 
						!value.GetType().IsAssignableFrom(typeof(CalendarCell)))
					{
						throw new InvalidCastException("Must be a CalendarCell");
					}
					base.CellTemplate = value;
				}
			}
		}

		public class CalendarCell : DataGridViewTextBoxCell
		{

			public CalendarCell()
				: base()
			{
				// Use the short date format.
				this.Style.Format = "d";
			}

			public override void InitializeEditingControl(int rowIndex, object 
				initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
			{
				// Set the value of the editing control to the current cell value.
				base.InitializeEditingControl(rowIndex, initialFormattedValue, 
					dataGridViewCellStyle);
				CalendarEditingControl ctl = 
					DataGridView.EditingControl as CalendarEditingControl;
				try
				{
					ctl.Value = (DateTime)this.Value;
				}
				catch
				{
					ctl.Value = DateTime.Now;
				}
			}

			public override Type EditType
			{
				get
				{
					// Return the type of the editing contol that CalendarCell uses.
					return typeof(CalendarEditingControl);
				}
			}

			public override Type ValueType
			{
				get
				{
					// Return the type of the value that CalendarCell contains.
					return typeof(DateTime);
				}
			}

			public override object DefaultNewRowValue
			{
				get
				{
					// Use the current date and time as the default value.
					//return DateTime.Now;
					return null;
				}
			}
		}

		class CalendarEditingControl : DateTimePicker, IDataGridViewEditingControl
		{
			DataGridView dataGridView;
			private bool valueChanged = false;
			int rowIndex;

			public CalendarEditingControl()
			{
				this.Format = DateTimePickerFormat.Short;
			}

			// Implements the IDataGridViewEditingControl.EditingControlFormattedValue 
			// property.
			public object EditingControlFormattedValue
			{
				get
				{
					return this.Value.ToShortDateString();
				}
				set
				{
					if (value is String)
					{
						this.Value = DateTime.Parse((String)value);
					}
				}
			}

			// Implements the 
			// IDataGridViewEditingControl.GetEditingControlFormattedValue method.
			public object GetEditingControlFormattedValue(
				DataGridViewDataErrorContexts context)
			{
				return EditingControlFormattedValue;
			}

			// Implements the 
			// IDataGridViewEditingControl.ApplyCellStyleToEditingControl method.
			public void ApplyCellStyleToEditingControl(
				DataGridViewCellStyle dataGridViewCellStyle)
			{
				this.Font = dataGridViewCellStyle.Font;
				this.CalendarForeColor = dataGridViewCellStyle.ForeColor;
				this.CalendarMonthBackground = dataGridViewCellStyle.BackColor;
			}

			// Implements the IDataGridViewEditingControl.EditingControlRowIndex 
			// property.
			public int EditingControlRowIndex
			{
				get
				{
					return rowIndex;
				}
				set
				{
					rowIndex = value;
				}
			}

			// Implements the IDataGridViewEditingControl.EditingControlWantsInputKey 
			// method.
			public bool EditingControlWantsInputKey(
				Keys key, bool dataGridViewWantsInputKey)
			{
				// Let the DateTimePicker handle the keys listed.
				switch (key & Keys.KeyCode)
				{
					case Keys.Left:
					case Keys.Up:
					case Keys.Down:
					case Keys.Right:
					case Keys.Home:
					case Keys.End:
					case Keys.PageDown:
					case Keys.PageUp:
						return true;
					default:
						return !dataGridViewWantsInputKey;
				}
			}

			// Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit 
			// method.
			public void PrepareEditingControlForEdit(bool selectAll)
			{
				// No preparation needs to be done.
			}

			// Implements the IDataGridViewEditingControl
			// .RepositionEditingControlOnValueChange property.
			public bool RepositionEditingControlOnValueChange
			{
				get
				{
					return false;
				}
			}

			// Implements the IDataGridViewEditingControl
			// .EditingControlDataGridView property.
			public DataGridView EditingControlDataGridView
			{
				get
				{
					return dataGridView;
				}
				set
				{
					dataGridView = value;
				}
			}

			// Implements the IDataGridViewEditingControl
			// .EditingControlValueChanged property.
			public bool EditingControlValueChanged
			{
				get
				{
					return valueChanged;
				}
				set
				{
					valueChanged = value;
				}
			}

			// Implements the IDataGridViewEditingControl
			// .EditingPanelCursor property.
			public Cursor EditingPanelCursor
			{
				get
				{
					return base.Cursor;
				}
			}

			protected override void OnValueChanged(EventArgs eventargs)
			{
				// Notify the DataGridView that the contents of the cell
				// have changed.
				valueChanged = true;
				this.EditingControlDataGridView.NotifyCurrentCellDirty(true);
				base.OnValueChanged(eventargs);
			}
		}
	}
}
To get blank cells on the calendar, all I have done is in the public override object DefaultNewRowValue function is to remove the return value and return NULL instead (I've commented it out and left it in for reference).

I also modified the InitializeEditingControl function to put a try/catch around the part which reads the value from the cell when initializing the calendar cell. If the TRY picks up a NULL, the code falls through to the CATCH statement which just uses DateTime.Now to initialize the calendar which is acceptable! If I decide I am editing the wrong cell, the ESCAPE key still reverts to a blank cell which is great!

Thanks for looking into this, I will see how I go with this one. Hopefully it may help someone else!

Sean
Sean Connolly  Wednesday, August 05, 2009 11:40 AM

You can use google to search for other answers

Custom Search

More Threads

• Setting Colors By Reference
• how to define a global parameter to use in all forms?
• LinkLabel
• Capturing Mouse Clicks outside UserControl
• Windows form properties and Property Window
• How can I set focus in a web broswer on winform?
• Custom control can't be resized with mouse using Width Property
• How to avoid loops with handlers?
• WYSIWYG HTML Editor Control
• Add url to PageView in windows forms