G
Guy
I have extended the datetimepicker control to incorporate
a ReadOnly property.
I have used the new keyword to implement my own version
of the value property, so that if readonly == true then
it will not set the value of the control and will leave
the checked status of the checkbox to false when a user
selects a new date.
this works fine when using the control on a win2k machine
but if we use it on a win XP box and call
Application.EnableVisualStyles() then it seems to ignore
my code and check the checkbox and set the value. this is
extremely buggy behaviour! and also the value property
gets called twice (only once on a win2k box).
i have also noticed behaviour changes in the
label.textalignment property when using XP Visual styles
aswell. Below is my implementation of the extended
datetimepicker and also the new data type
(OptionalDateTime) that is used for the value property...
#####LockableDateTimePicker Source###########
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using HCS.DataTypes;
namespace HCS.Generic.UI.Controls
{
/// <summary>
/// LockableDateTimePicker is for selecting
dates. It manipulates the OptionalDateTime
/// class to allow null dates to be handled.
/// </summary>
public class LockableDateTimePicker :
DateTimePicker
{
#region Clean Up Code
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool
disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose
();
}
}
base.Dispose( disposing );
}
#endregion
#region Component Designer generated code
/// <summary>
/// Required method for Designer support -
do not modify
/// the contents of this method with the
code editor.
/// </summary>
private void InitializeComponent()
{
components = new
System.ComponentModel.Container();
}
#endregion
#region Fields
private System.ComponentModel.Container
components = null;
private bool mReadOnly;
private DateTime mDateTime;
private Color mBackColor;
private Color mLockedColor;
private bool mChecked;
#endregion
#region Events
public event OnReadOnlyChangedDelegate
OnReadOnlyChanged;
#endregion
#region EventArgs and Delegates
public class OnReadOnlyChangedEventArgs :
EventArgs
{
private bool mReadOnly;
public OnReadOnlyChangedEventArgs
(bool ReadOnly)
{
mReadOnly = ReadOnly;
}
public bool ReadOnly
{
get
{
return mReadOnly;
}
}
}
public delegate void
OnReadOnlyChangedDelegate(object sender,
OnReadOnlyChangedEventArgs e);
#endregion
#region Constructor
public LockableDateTimePicker()
{
// This call is required by the
Windows.Forms Form Designer.
InitializeComponent();
mBackColor =
base.CalendarMonthBackground;
mLockedColor =
base.CalendarMonthBackground;
//Set defaults for this control
base.Format =
DateTimePickerFormat.Short;
//Make sure that our date backup
is populated
mDateTime = base.Value;
mChecked = base.Checked;
}
#endregion
#region Properties
[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public bool ReadOnly
{
get
{
return mReadOnly;
}
set
{
if(value)
{
base.CalendarMonthBackground = mLockedColor;
}
else
{
base.CalendarMonthBackground = mBackColor;
}
mReadOnly = value;
if(OnReadOnlyChanged !=
null)
{
OnReadOnlyChanged
(this, new OnReadOnlyChangedEventArgs(value));
}
}
}
[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public Color LockedColor
{
get
{
return mLockedColor;
}
set
{
mLockedColor = value;
}
}
#endregion
#region Public Overridden Properties
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
mBackColor = value;
if(!mReadOnly)
{
base.BackColor =
value;
}
}
}
public new OptionalDateTime Value
{
set
{
if(value.GetValue() == "")
{
base.Checked =
false;
}
else
{
base.Value =
DateTime.Parse(value.GetValue());
}
}
get
{
if(base.Checked)
{
return new
OptionalDateTime(base.Value);
}
else
{
return new
OptionalDateTime();
}
}
}
#endregion
#region Public Overridden Events
protected override void OnValueChanged
(EventArgs eventargs)
{
base.OnValueChanged (eventargs);
if(mReadOnly)
{
//We need to set the
value of the control back to
//the stored value, since
it is read only
if(base.Value !=
mDateTime)
{
base.Value =
mDateTime;
}
if(base.Checked !=
mChecked)
{
base.Checked =
mChecked;
}
}
else
{
//Store the value for
when it's read only
mDateTime = base.Value;
mChecked = base.Checked;
}
}
#endregion
#region Public Methods
public void Initialise(OptionalDateTime
Value)
{
//Temporarily set the control to
not ReadOnly.
bool mTempReadOnly = mReadOnly;
if(mReadOnly)
{
mReadOnly = false;
}
if(Value.GetValue() == "")
{
base.Checked = false;
mChecked = false;
}
else
{
base.Value =
DateTime.Parse(Value.GetValue());
base.Checked = true;
mDateTime = base.Value;
mChecked = true;
}
//Make sure the ReadOnly value is
returned to normal
mReadOnly = mTempReadOnly;
}
public void Initialise(DateTime Value)
{
Initialise(new OptionalDateTime
(Value));
}
public void Initialise()
{
Initialise(new OptionalDateTime
());
}
#endregion
}
}
##############OptionalDateTime Source##########
[Serializable()]
public class OptionalDateTime
{
#region Enum
/// <summary>
/// Formats available - extend as
required, but remember to update <see cref="GetValue"/>.
/// </summary>
public enum enumDateTimeFormat
{
/// <summary>
/// LongDateFormat
/// </summary>
LongDateFormat,
/// <summary>
/// LongTimeFormat
/// </summary>
LongTimeFormat,
/// <summary>
/// ShortDateFormat
/// </summary>
ShortDateFormat,
/// <summary>
/// ShortTimeFormat
/// </summary>
ShortTimeFormat
}
#endregion
#region Fields
private DateTime mDate;
private bool mIsNull;
#endregion
#region Constructor
/// <summary>
/// Constructor - initialises a null
OptionalDateTime
/// </summary>
public OptionalDateTime()
{
mIsNull = true;
}
/// <summary>
/// Constructor - initialise an
OptionalDateTime to contain the value of a string.
/// If the string is not a valid
DateTime, the object is set to contain a null date.
/// </summary>
/// <param name="value">A string
representing a valid date.</param>
public OptionalDateTime(string value)
{
SetValue(value);
}
/// <summary>
/// Constructor - initialise an
OptionalDateTime to contain the value of a DateTime.
/// </summary>
/// <param name="value">A DateTime value
type.</param>
public OptionalDateTime(DateTime value)
{
SetValue(value);
}
#endregion
#region Public Methods
/// <summary>
/// Set the value of the object to equal
that of a DateTime.
/// </summary>
/// <param name="value">A
DateTime.</param>
public void SetValue(DateTime value)
{
mDate = value;
mIsNull = false;
}
/// <summary>
/// Set the value of the object to equal
that of a string. If the string is not a valid
/// DateTime, the object is set to
contain a null date.
/// </summary>
/// <param name="value">A string
representing a valid date.</param>
public void SetValue(string value)
{
if(value == null || value == "")
{
mIsNull = true;
}
else
{
try
{
mDate =
DateTime.Parse(value);
mIsNull = false;
}
catch
{
throw new
ArgumentException("The string entered cannot be converted
to a DateTime", "value");
}
}
}
/// <summary>
/// Return the value of the object as a
string with optional formatting.
/// </summary>
/// <param name="Format">The format to
return.</param>
/// <returns>A string containing the
correctly formatted date.</returns>
public string GetValue(enumDateTimeFormat
Format)
{
if(mIsNull)
{
return "";
}
else
{
switch(Format)
{
case
enumDateTimeFormat.LongDateFormat:
return
mDate.ToLongDateString();
case
enumDateTimeFormat.LongTimeFormat:
return
mDate.ToLongTimeString();
case
enumDateTimeFormat.ShortDateFormat:
return
mDate.ToShortDateString();
case
enumDateTimeFormat.ShortTimeFormat:
return
mDate.ToShortTimeString();
default:
throw new
UnhandledDateFormatException(Format);
}
}
}
/// <summary>
/// Return the value of the object as a
ShortDateString.
/// </summary>
/// <returns></returns>
public string GetValue()
{
return GetValue
(enumDateTimeFormat.ShortDateFormat);
}
#endregion
#region Public Override Methods
/// <summary>
/// Passes a string containing the date
in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
/// </summary>
/// <returns>The date returned. Passes an
empty string for blank (null) dates.</returns>
public override string ToString()
{
return GetValue();
}
#endregion
#region Properties
/// <summary>
/// Returns the date of the
OptionalDateTime as a DateTime type. Raises the
/// <see
cref="OptionalDateTimeIsNullException"/> if the
OptionalDateTime is
/// blank (null). Check the <see
cref="IsNull"/> property before calling this
/// method to avoid the exception.
/// </summary>
public DateTime GetDateTime
{
get
{
if(mIsNull)
{
throw new
OptionalDateTimeIsNullException();
}
return mDate;
}
}
/// <summary>
/// Gets a boolean value indicating
whether the OptionalDateTime is blank (null).
/// </summary>
public bool IsNull
{
get
{
return mIsNull;
}
}
#endregion
}
thanks in advance
a ReadOnly property.
I have used the new keyword to implement my own version
of the value property, so that if readonly == true then
it will not set the value of the control and will leave
the checked status of the checkbox to false when a user
selects a new date.
this works fine when using the control on a win2k machine
but if we use it on a win XP box and call
Application.EnableVisualStyles() then it seems to ignore
my code and check the checkbox and set the value. this is
extremely buggy behaviour! and also the value property
gets called twice (only once on a win2k box).
i have also noticed behaviour changes in the
label.textalignment property when using XP Visual styles
aswell. Below is my implementation of the extended
datetimepicker and also the new data type
(OptionalDateTime) that is used for the value property...
#####LockableDateTimePicker Source###########
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using HCS.DataTypes;
namespace HCS.Generic.UI.Controls
{
/// <summary>
/// LockableDateTimePicker is for selecting
dates. It manipulates the OptionalDateTime
/// class to allow null dates to be handled.
/// </summary>
public class LockableDateTimePicker :
DateTimePicker
{
#region Clean Up Code
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool
disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose
();
}
}
base.Dispose( disposing );
}
#endregion
#region Component Designer generated code
/// <summary>
/// Required method for Designer support -
do not modify
/// the contents of this method with the
code editor.
/// </summary>
private void InitializeComponent()
{
components = new
System.ComponentModel.Container();
}
#endregion
#region Fields
private System.ComponentModel.Container
components = null;
private bool mReadOnly;
private DateTime mDateTime;
private Color mBackColor;
private Color mLockedColor;
private bool mChecked;
#endregion
#region Events
public event OnReadOnlyChangedDelegate
OnReadOnlyChanged;
#endregion
#region EventArgs and Delegates
public class OnReadOnlyChangedEventArgs :
EventArgs
{
private bool mReadOnly;
public OnReadOnlyChangedEventArgs
(bool ReadOnly)
{
mReadOnly = ReadOnly;
}
public bool ReadOnly
{
get
{
return mReadOnly;
}
}
}
public delegate void
OnReadOnlyChangedDelegate(object sender,
OnReadOnlyChangedEventArgs e);
#endregion
#region Constructor
public LockableDateTimePicker()
{
// This call is required by the
Windows.Forms Form Designer.
InitializeComponent();
mBackColor =
base.CalendarMonthBackground;
mLockedColor =
base.CalendarMonthBackground;
//Set defaults for this control
base.Format =
DateTimePickerFormat.Short;
//Make sure that our date backup
is populated
mDateTime = base.Value;
mChecked = base.Checked;
}
#endregion
#region Properties
[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public bool ReadOnly
{
get
{
return mReadOnly;
}
set
{
if(value)
{
base.CalendarMonthBackground = mLockedColor;
}
else
{
base.CalendarMonthBackground = mBackColor;
}
mReadOnly = value;
if(OnReadOnlyChanged !=
null)
{
OnReadOnlyChanged
(this, new OnReadOnlyChangedEventArgs(value));
}
}
}
[DesignerSerializationVisibility
(DesignerSerializationVisibility.Visible)]
public Color LockedColor
{
get
{
return mLockedColor;
}
set
{
mLockedColor = value;
}
}
#endregion
#region Public Overridden Properties
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
mBackColor = value;
if(!mReadOnly)
{
base.BackColor =
value;
}
}
}
public new OptionalDateTime Value
{
set
{
if(value.GetValue() == "")
{
base.Checked =
false;
}
else
{
base.Value =
DateTime.Parse(value.GetValue());
}
}
get
{
if(base.Checked)
{
return new
OptionalDateTime(base.Value);
}
else
{
return new
OptionalDateTime();
}
}
}
#endregion
#region Public Overridden Events
protected override void OnValueChanged
(EventArgs eventargs)
{
base.OnValueChanged (eventargs);
if(mReadOnly)
{
//We need to set the
value of the control back to
//the stored value, since
it is read only
if(base.Value !=
mDateTime)
{
base.Value =
mDateTime;
}
if(base.Checked !=
mChecked)
{
base.Checked =
mChecked;
}
}
else
{
//Store the value for
when it's read only
mDateTime = base.Value;
mChecked = base.Checked;
}
}
#endregion
#region Public Methods
public void Initialise(OptionalDateTime
Value)
{
//Temporarily set the control to
not ReadOnly.
bool mTempReadOnly = mReadOnly;
if(mReadOnly)
{
mReadOnly = false;
}
if(Value.GetValue() == "")
{
base.Checked = false;
mChecked = false;
}
else
{
base.Value =
DateTime.Parse(Value.GetValue());
base.Checked = true;
mDateTime = base.Value;
mChecked = true;
}
//Make sure the ReadOnly value is
returned to normal
mReadOnly = mTempReadOnly;
}
public void Initialise(DateTime Value)
{
Initialise(new OptionalDateTime
(Value));
}
public void Initialise()
{
Initialise(new OptionalDateTime
());
}
#endregion
}
}
##############OptionalDateTime Source##########
[Serializable()]
public class OptionalDateTime
{
#region Enum
/// <summary>
/// Formats available - extend as
required, but remember to update <see cref="GetValue"/>.
/// </summary>
public enum enumDateTimeFormat
{
/// <summary>
/// LongDateFormat
/// </summary>
LongDateFormat,
/// <summary>
/// LongTimeFormat
/// </summary>
LongTimeFormat,
/// <summary>
/// ShortDateFormat
/// </summary>
ShortDateFormat,
/// <summary>
/// ShortTimeFormat
/// </summary>
ShortTimeFormat
}
#endregion
#region Fields
private DateTime mDate;
private bool mIsNull;
#endregion
#region Constructor
/// <summary>
/// Constructor - initialises a null
OptionalDateTime
/// </summary>
public OptionalDateTime()
{
mIsNull = true;
}
/// <summary>
/// Constructor - initialise an
OptionalDateTime to contain the value of a string.
/// If the string is not a valid
DateTime, the object is set to contain a null date.
/// </summary>
/// <param name="value">A string
representing a valid date.</param>
public OptionalDateTime(string value)
{
SetValue(value);
}
/// <summary>
/// Constructor - initialise an
OptionalDateTime to contain the value of a DateTime.
/// </summary>
/// <param name="value">A DateTime value
type.</param>
public OptionalDateTime(DateTime value)
{
SetValue(value);
}
#endregion
#region Public Methods
/// <summary>
/// Set the value of the object to equal
that of a DateTime.
/// </summary>
/// <param name="value">A
DateTime.</param>
public void SetValue(DateTime value)
{
mDate = value;
mIsNull = false;
}
/// <summary>
/// Set the value of the object to equal
that of a string. If the string is not a valid
/// DateTime, the object is set to
contain a null date.
/// </summary>
/// <param name="value">A string
representing a valid date.</param>
public void SetValue(string value)
{
if(value == null || value == "")
{
mIsNull = true;
}
else
{
try
{
mDate =
DateTime.Parse(value);
mIsNull = false;
}
catch
{
throw new
ArgumentException("The string entered cannot be converted
to a DateTime", "value");
}
}
}
/// <summary>
/// Return the value of the object as a
string with optional formatting.
/// </summary>
/// <param name="Format">The format to
return.</param>
/// <returns>A string containing the
correctly formatted date.</returns>
public string GetValue(enumDateTimeFormat
Format)
{
if(mIsNull)
{
return "";
}
else
{
switch(Format)
{
case
enumDateTimeFormat.LongDateFormat:
return
mDate.ToLongDateString();
case
enumDateTimeFormat.LongTimeFormat:
return
mDate.ToLongTimeString();
case
enumDateTimeFormat.ShortDateFormat:
return
mDate.ToShortDateString();
case
enumDateTimeFormat.ShortTimeFormat:
return
mDate.ToShortTimeString();
default:
throw new
UnhandledDateFormatException(Format);
}
}
}
/// <summary>
/// Return the value of the object as a
ShortDateString.
/// </summary>
/// <returns></returns>
public string GetValue()
{
return GetValue
(enumDateTimeFormat.ShortDateFormat);
}
#endregion
#region Public Override Methods
/// <summary>
/// Passes a string containing the date
in <see cref="enumDateTimeFormat.ShortDateFormat"/>.
/// </summary>
/// <returns>The date returned. Passes an
empty string for blank (null) dates.</returns>
public override string ToString()
{
return GetValue();
}
#endregion
#region Properties
/// <summary>
/// Returns the date of the
OptionalDateTime as a DateTime type. Raises the
/// <see
cref="OptionalDateTimeIsNullException"/> if the
OptionalDateTime is
/// blank (null). Check the <see
cref="IsNull"/> property before calling this
/// method to avoid the exception.
/// </summary>
public DateTime GetDateTime
{
get
{
if(mIsNull)
{
throw new
OptionalDateTimeIsNullException();
}
return mDate;
}
}
/// <summary>
/// Gets a boolean value indicating
whether the OptionalDateTime is blank (null).
/// </summary>
public bool IsNull
{
get
{
return mIsNull;
}
}
#endregion
}
thanks in advance