So I did actually get this to work.
Since I'm using databinding to business objects (rather than a dataset or
datatable), I added another property to my class that is a string. So I
have the original nullable date field (StartDate) and the string
representation of it (textStartDate).
I data bound the textStartDate to the masked text box, with a format of
##/##/## so the user can only put in numbers.
When it loads the data from the database, it formats StartDate into
MM/dd/yy format and stuff it into textStartDate.
In the Set accessor for textStartDate, which is fired by the validation
when the user tabs out of the field, it checks the value. If it's null or
"" or " / /", then there is no date, and it sets StartDate to null. If it
has value, it is validates as a date, and if it's valid, it sets StartDate
to that date.
This way, the user can delete the date and I don't get errors about it
being an invalid date from the databinding. But I still have date
validation.
Robin S.
-----------------------------------
RobinS said:
I'm actually using C#. I wanted to do a masked textbox, but if I
ultimately can't get it to work, I'll definitely try out this project.
Thanks for the link.
Robin S.
--------------------------------
Jay Parzych said:
here is one that will:
http://www.codeproject.com/cs/miscctrl/NullableDateTimePicker.asp
i actually downloaded the vb.net version here:
http://www.grazioli.ch/Blog/PermaLink.aspx?guid=c4a63d35-71f9-4b02-9de7-0c87e5b1c770
whats nice is you can set the value to be displayed. i chose "Click to
Set" in one of my applications
i have not yet figured out how to make this usable for a datagridview
column
It won't work with a bound business object?
I have discovered if the user puts in 00/00/00 it will let him out of
the field if I have nullvalue set to 00/00/00, and it stores null. I
just thought it would be nice to show nothing, and let the user blank
out the data.
Robin S.
-----------------------------------
Hi;
Try my DTextBox. It does the following:
1) Inherits the TextBox. Therefore, you have a data bindable textbox
for entering dates
2) If you enter a text that is not a valid date string, it can write
DBNull into your dataTable
3) It can show the calendar for you to pick a date if you right-click
it (this is commented out)
I know this might not be exactly what you're looking for, but I hope
it helps.
The basic idea is that you can inherit from the TextBox and make a new
one which performs as you want. I've spent a lot of time trying to
figure out how to do it without programming and in the end I gave up
and wrote this.
It may not be perfect, as it only works if it is bound to a datacolumn
in a datatable.
Djordje
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
namespace FizikaMerenja2006.UserCtls
{
/// <summary>
/// Text box used for date entry in data-bound mode
/// </summary>
class DTextBox: TextBox
{
public DTextBox()
: base()
{
//ContextMenu cm = new ContextMenu();
//cm.Popup += new EventHandler(cm_Popup);
//this.ContextMenu = cm;
this.MouseUp += new MouseEventHandler(DTextBox_MouseUp);
this.GotFocus += new EventHandler(DTextBox_GotFocus);
this.LostFocus += new EventHandler(DTextBox_LostFocus);
}
#region ------ BackColorActive ----------
private bool prviPut = true;
private Color originalBackColor;
private Color backColorFocused = Color.White;
[Browsable(true)]
[Category("Appearance")]
[Description("The background color when the component has
focus.")]
public Color BackColorFocused
{
get { return backColorFocused; }
set { backColorFocused = value; }
}
void DTextBox_LostFocus(object sender, EventArgs e)
{
this.BackColor = originalBackColor;
}
void DTextBox_GotFocus(object sender, EventArgs e)
{
if (prviPut)
{
originalBackColor = this.BackColor;
prviPut = false;
}
this.BackColor = backColorFocused;
}
#endregion
void cm_Popup(object sender, EventArgs e)
{
prikaziDatum();
}
// COMMENT THIS METHOD OUT as it calls a form for which you
don't have the source code
private void prikaziDatum()
{
frmDatePicker frm = new frmDatePicker();
System.Drawing.Point loc = this.Parent.Location;
loc.Offset(this.Location);
loc.Offset(this.Width,0);
frm.Location = loc;
frm.DateSelected += delegate(object sndr,
DateRangeEventArgs dee) { this.Text = dee.Start.ToShortDateString();
frm.Close(); };
frm.LostFocus += delegate(object sndr, EventArgs eargs)
{ ((Form)sndr).Close(); };
frm.Show();
}
void DTextBox_MouseUp(object sender, MouseEventArgs e)
{
}
private bool _EmptyTextIsDBNull = true;
/// <summary>
/// If true, the input which is not a valid date string will
be written as DBNull into the bound DataTable.
/// Works only with DataTables.
/// Odreduje da li se unos koji se ne prepoznaje kao datum
zapisuje kao DBNull u povezanu
/// bazu, ukoliko je kontrola vezana na polje u DataTable
objektu.
/// </summary>
[Browsable(true),Category("Data"), DefaultValue(true)]
public bool EmptyTextIsDBNull
{
get
{
return _EmptyTextIsDBNull;
}
set
{
_EmptyTextIsDBNull = value;
}
}
protected override void
OnValidating(System.ComponentModel.CancelEventArgs e)
{
// Do the default validation if the extra checking is off
if (!_EmptyTextIsDBNull)
{
base.OnValidating(e);
return;
}
// On the other hand, if extra checking is on, we perform
only our validation,
// which writes a DBNull.Value into the bound DataTable if
you enter an invalid date.
try
{
Binding b = this.DataBindings["Text"];
BindingMemberInfo bmi = b.BindingMemberInfo;
string fieldname = bmi.BindingField;
BindingSource bs = ((BindingSource)b.DataSource);
System.Data.DataRow dr =
((System.Data.DataRowView)bs.Current).Row;
string tn =
dr.Table.Columns[fieldname].DataType.FullName;
bool an = dr.Table.Columns[fieldname].AllowDBNull;
if (tn != "System.DateTime")
{
base.OnValidating(e);
return;
}
// try
// {
//DateTime.Parse(this.Text);
base.OnValidating(e);
//}
//catch
//{
if ((e.Cancel==true) && (an))
{
dr[fieldname] = System.Convert.DBNull;
base.OnTextChanged(new EventArgs());
bs.ResetBindings(false);
e.Cancel = false;
}
//else
//{
// e.Cancel = true;
//}
//}
}
catch
{
base.OnValidating(e);
}
}
private void InitializeComponent()
{
this.SuspendLayout();
this.ResumeLayout(false);
}
}
}