 |
|
 |
Hello,
I use your code, because it is elegant, simple and efficient, as Phil Raevsky said. I have used all remarks from the forum and found some new upgrades.
public class NullableDateTimePicker : System.Windows.Forms.DateTimePicker { DateTimePickerFormat _Format; string _CustomFormat; private DateTime? _ValueNullable;
public NullableDateTimePicker() : base() { _Format = base.Format; _CustomFormat = base.CustomFormat; }
public new DateTimePickerFormat Format { get { return base.Format; } set { this._Format = value; base.Format = value; } } public new string CustomFormat { get { return base.CustomFormat; } set { this._CustomFormat = value; base.CustomFormat = value; } }
public DateTime? ValueNullable { get { return _ValueNullable; } set { _ValueNullable = value; if(!_ValueNullable.HasValue || value <= this.MinDate || value >= this.MaxDate) { base.Format = DateTimePickerFormat.Custom; base.CustomFormat = " "; base.OnValueChanged(EventArgs.Empty); } else { base.Format = _Format; base.CustomFormat = _CustomFormat; base.Value = _ValueNullable.Value; } } }
public new DateTime Value { get { if(!_ValueNullable.HasValue) return this.MinDate; return ValueNullable.Value; } set { this.ValueNullable = value; } }
protected override void OnKeyDown(KeyEventArgs e) { ... } protected override void OnCloseUp(EventArgs eventargs) { ... } }
Hope that could help.
Romain TAILLANDIER www.romaintaillandier.blogspot.com romaintaillandier.free.fr www.maintag.fr
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Imports System Imports System.Windows.Forms Namespace Controls Public Class DateTimePicker Inherits System.Windows.Forms.DateTimePicker Private bIsNull As Boolean = False Private mBackColor As Color = SystemColors.Window Public Sub New() MyBase.New() End Sub Public Shadows Property Value() As DateTime Get If bIsNull Then Return DateTime.MinValue Else Return MyBase.Value End If End Get Set(ByVal value As DateTime) If value = DateTime.MinValue Or value.Date = "01/01/1905" Or value.Date = "01/01/1900" Then If bIsNull = False Then bIsNull = True MakePinkFormat() Else MakeWhiteFormat() bIsNull = False MyBase.Value = value End If End Set End Property ' Protected Overloads Overrides Sub OnCloseUp(ByVal eventargs As EventArgs) Protected Overrides Sub OnCloseUp(ByVal eventargs As EventArgs)
If Control.MouseButtons = MouseButtons.None Or Control.MouseButtons = Windows.Forms.MouseButtons.Left Then Me.Value = MyBase.Value End If MyBase.OnCloseUp(eventargs) End Sub Protected Overloads Overrides Sub OnKeyDown(ByVal e As KeyEventArgs) MyBase.OnKeyDown(e)
If e.KeyCode = Keys.Delete Then Me.Value = DateTime.MinValue MyBase.Value = "01/01/1905" End If End Sub Private Sub MakePinkFormat() Me.Format = DateTimePickerFormat.[Custom] Me.BackColor = Color.Pink Me.CustomFormat = " " MyBase.Value = "01/01/1905" End Sub Private Sub MakeWhiteFormat() Me.Format = DateTimePickerFormat.Short Me.BackColor = Color.White Me.CustomFormat = Nothing End Sub 'The BackColor property we will be calling Public Overrides Property BackColor() As Color Get Return mBackColor End Get Set(ByVal Value As Color) mBackColor = Value 'After the BackColor has been set, Invalidate the control 'This will force it to be redrawn 'Me.Invalidate() End Set End Property 'WndProc fires durring the painting of the control Protected Overrides Sub WndProc(ByRef m As Message) 'Check to see if message being send is WM_ERASEBKGND. 'The hex value of this message is &H14. 'This message is sent when the background of the 'object needs to be erased. In our case though, instead of 'erasing it, we will paint a rectangle over it If m.Msg = CInt(&H14) Then ' WM_ERASEBKGND Dim g As Graphics = Graphics.FromHdc(m.WParam) g.FillRectangle(New SolidBrush(mBackColor), ClientRectangle) g.Dispose() Return End If MyBase.WndProc(m) End Sub Private Sub DateTimePicker_EnabledChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.EnabledChanged Me.CalendarForeColor = Color.Black End Sub End Class End Namespace
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This is an edit because I realized, like the previous poster, than you can simply shadow the Value property of the base DateTimePicker to allow Nullable Dates. That means that it works exactly like you would want/expect it to, in databinding situations and everything.
Public Class NullableDateTimeControl Inherits System.Windows.Forms.DateTimePicker
Private oldFormat As DateTimePickerFormat = DateTimePickerFormat.Short Private oldCustomFormat As String = Nothing Private _IsNull As Boolean = False
Public Sub New() MyBase.New() End Sub
''' <summary> ''' The Date Value of the control (is Nullable, can be set to Nothing). ''' </summary> ''' <value></value> ''' <returns></returns> ''' <remarks></remarks> Public Shadows Property Value() As Date? Get
If Me._IsNull Then
Return Nothing
Else
Return MyBase.Value
End If
End Get Set(ByVal newValue As Date?)
If Not newValue.HasValue Then
If Not Me._IsNull Then
Me.oldFormat = Me.Format Me.oldCustomFormat = Me.CustomFormat Me._IsNull = True
End If
Me.Format = DateTimePickerFormat.Custom Me.CustomFormat = " "
Else
If Me._IsNull Then
Me.Format = Me.oldFormat Me.CustomFormat = Me.oldCustomFormat Me._IsNull = False
End If
MyBase.Value = newValue.Value
End If
End Set End Property
''' <summary> ''' Allows the user to select a new date if the control is already null. ''' </summary> ''' <param name="eventargs"></param> ''' <remarks></remarks> Protected Overrides Sub OnCloseUp(ByVal eventargs As System.EventArgs)
If Control.MouseButtons = Windows.Forms.MouseButtons.None Then
If Me._IsNull Then
Me.Format = Me.oldFormat Me.CustomFormat = Me.oldCustomFormat Me._IsNull = False
End If
End If
MyBase.OnCloseUp(eventargs)
End Sub
''' <summary> ''' Overrides the base class implementation to allow the user to create a Null value by pressing the Delete key. ''' </summary> ''' <param name="e"></param> ''' <remarks></remarks> Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs) MyBase.OnKeyUp(e)
If e.KeyCode = Keys.Delete Then
Me.Value = DateTime.MinValue
End If
End Sub
End Class
modified on Wednesday, February 11, 2009 10:51 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, i wanna know if this code can be used in visual studio 2008 (visual basic) or i need to make some changes to use them.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
This way you can actually have a null value for the control.
public new DateTime ? Value { get { if (bIsNull) return null; else return base.Value; } set { if (value == null) { if (bIsNull == false) { oldFormat = this.Format; oldCustomFormat = this.CustomFormat; bIsNull = true; }
this.Format = DateTimePickerFormat.Custom; this.CustomFormat = " "; } else { if (bIsNull) { this.Format = oldFormat; this.CustomFormat = oldCustomFormat; bIsNull = false; } base.Value = value.Value; } } }
protected override void OnCloseUp(EventArgs eventargs) { if (Control.MouseButtons == MouseButtons.None) { if (bIsNull) { this.Format = oldFormat; this.CustomFormat = oldCustomFormat; bIsNull = false; } } base.OnCloseUp (eventargs); }
protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown (e);
if (e.KeyCode == Keys.Delete) this.Value = null; }
|
| Sign In·View Thread·PermaLink | 2.50/5 (5 votes) |
|
|
|
 |
|
|
 |
|
 |
When used out-of-the-box, the user must use the mouse to enter a date once the value has been set to DateTime.MinValue.
Change the KeyUp override as follows:
protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e);
if (e.KeyCode == Keys.Delete) this.Value = DateTime.MinValue;
else if (this.Value == DateTime.MinValue && (e.KeyCode == Keys.Space || Char.IsNumber((char)e.KeyValue) || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)) this.Value = DateTime.Today; }
This allows the user to get the "normal" date in the box after pressing a space, any arrow key, or any number.
Comments?
|
| Sign In·View Thread·PermaLink | 4.25/5 (3 votes) |
|
|
|
 |
|
 |
While this allowed the control to go back to edit mode after it was set to null, I didn't like the way it would go back to Today's date. The reason being... Today is 09/09/09. Well, lets say I want to go into that field and enter in an April date, I will hit 4 and it will display 09/09/2009. I will have to hit 4 again to enter the April date.
I tried moving the base.OnKeyUp(e) call after the code to set today's date so it would persist the 4 into the control and that didn't work. Then I tried moving the code to the OnKeyDown event handler. That didn't work either. So I found away around it be using some date manipulation:
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyCode == Keys.Delete) { this.Value = null; } else if ((this.Value == DateTime.MinValue || this.Value == null) && (e.KeyCode == Keys.Space || Char.IsNumber((char)e.KeyValue) || e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Right || e.KeyCode == Keys.Left)) { DateTime newDate = DateTime.Today; if (Char.IsNumber((char)e.KeyValue)) { newDate = DateTime.Parse(string.Format("{0}/{1}/{2}", (char)e.KeyValue, DateTime.Today.Day, DateTime.Today.Year)); } this.Value = newDate; } base.OnKeyDown(e);
}
NOTE: I have also included a check for this.Value == null because I also altered the class to use a Nullable(DateTime). Also, this is in the OnKeyDown event. I moved this from the previously suggested OnKeyUp. I think it will work either way, though.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I found this pretty usefull, but do you know a way to place a button in the calendar to place the null value? like the "today" button there is in the lower left corner... I'm using vb.net :P just so you know.
thanks!
|
| Sign In·View Thread·PermaLink | 2.00/5 (4 votes) |
|
|
|
 |
|
 |
The sample project doesn't work for me -- pressing delete does nothing. What gives?
How do I use this control in a project?
Relative performance is no substitute for absolute achievement.
|
| Sign In·View Thread·PermaLink | 1.56/5 (9 votes) |
|
|
|
 |
|
 |
I like it 
Actually change Value so it is a "DateTime?", much nicer And also I used both Delete & Backspace for having an empty date
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
When NullableDateTimePicker (NDTP) state is null and it doesn't show value, click on the dropdown and select current value at the bottom of the dropdown, near red circle mark. This should change the NDTP state to not-null and show current DateTime. But NDTP checks if user selected value in dropdown by checking that no mouse button is pressed (in OnCloseUp), which is true only if a calendar was clicked, but not if bottom mark was clicked. IMO, there is solution for this is not to rely on mouse button state in OnCloseUp. Instead override OnValueChanged and set a flag, then use it in OnCloseUp. Thus:
protected override void OnCloseUp(EventArgs eventargs) { if (Control.MouseButtons == MouseButtons.None || fHasValueChanged) { if (fIsNull) { this.Format = fOldFormat; this.CustomFormat = fOldCustomFormat; fIsNull = false; } fHasValueChanged = false; } base.OnCloseUp(eventargs); } protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.KeyCode == Keys.Delete) { this.Value = DateTime.MinValue; this.fHasValueChanged = false; } } protected override void OnValueChanged(EventArgs eventargs) { fHasValueChanged = true; base.OnValueChanged(eventargs); }
Resetting to false in OnKeyUp has to be done, because user can change value by hand, not by dropdown. In such case the flag remains true which could cause problems if user presses delete on NDTP and then pressed and depressed dropdown arrow (without changing value). If flag is not reset when she pressed delete, than suddenly NDTP would show value.
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
 |
hi all,
i am using sql server and vb.net 2002 to develop my project. the problem i face now is when i bind the null value (datatype = datetime) into the date time picker control, it show an error
please help, i need the code in vb.net
loon
Have a nice day
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
I tried this version and binding a nullable datetime does not work, as it leaves the last valid date from a previous bind. Here is a different version that seems to work better. NB. 5 minutes of testing only. Just dataBind to the ValueNullable property as opposed to the Value property if you have a Nullable DateTime. This should work as normal if you have a normal DateTime (bind to Value).
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms;
namespace Invisage.PinkFloyd.Library.Controls { public class DateTimePickerNullable : System.Windows.Forms.DateTimePicker { DateTimePickerFormat mOriginaldateTimePickerFormat; private DateTime? mValueNullable;
public DateTimePickerNullable() : base() { mOriginaldateTimePickerFormat = base.Format; }
[Category("PinkFloyd")] [Description("Nullable DateTime")] [Bindable(true)] public DateTime? ValueNullable { get { return mValueNullable; } set { mValueNullable = value;
if (!mValueNullable.HasValue) { this.Format = DateTimePickerFormat.Custom; this.CustomFormat = " "; } else { this.Format = mOriginaldateTimePickerFormat; base.Value = mValueNullable.Value; } } }
protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown (e);
if (e.KeyCode == Keys.Delete) { ValueNullable = null; } } } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Have you tried pressing the Delete button when the ValueNullable it is bound? I think you'll find it doesn't work.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Your control could possibly be what I am looking for.
I want to be able to display either a blank space or a customer phrase (such as "No Date Entered" when the date is NULL.
Can your control handle this?
|
| Sign In·View Thread·PermaLink | 2.00/5 (2 votes) |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Hi Pham,
First off, excellent control. I have been looking far and wide for something like this, and I thought that I had found my solution in your control, but I am having difficulty placing it in a TabPage on a TabControl control AND data binding.
For example, if I start off with your DateTimePicker control in a TabPage container that is not by default displayed, no problem--I can choose the TabPage and it displays your control fine. Your control operates fine, and I can even set it to "null" (that is, DateTime.MinValue) before selecting the TabPage.
Now add databinding. If I have an additional private DateTime variable and in the form's Load event I add a custom databinding, e.g.
private DateTime dt = DateTime.MinValue;
private void Form1_Load(object sender, System.EventArgs e) { this.dateTimePicker1.DataBindings.Add("Value", dt, ""); }
then, when I display the TabPage containing the control, I receive:
An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in system.windows.forms.dll
Additional information: Error creating window handle.
Do you know any way to prevent this? Debugging seems to reveal that the error occurs somewhere in the Set clause, but I can't pinpoint it--very strange error.
Thanks! Mark
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Yep - this one got me too!
It is the change in DateTimePicker.Format when you are switching between a null date and a non-null date (or vice versa). The change in the value of Format causes the component to raise a notification which is normally ok. But in the case you described above the control is not visible yet and the Format notification fails internally.
The work around is to leave the Format as Custom and switch the CustomFormat format between " " for a null date value, and the appropriate format for the date eg for short - "dd/MM/yyyy".
Cheers,
Brett
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |