Groups | Blog | Home
all groups > dotnet windows forms databinding > april 2007 >

dotnet windows forms databinding : Databind a nullable date to a masked textbox


RobinS
4/15/2007 6:03:54 PM

Is there a way to databind a nullable date to a masked textbox?

I have a nullable date defined in a business object and have bound it to a
masked textbox, but when I clear out the date in the field, it will no
longer let me exit the field, and gives me an error that it is an invalid
format for a date. (duh!)

I bound it using the designer, and when that didn't work, tried doing it in
code. Here's my code:

Binding b = new Binding("Text", PlanListBindingSource, "StartDate", true,
DataSourceUpdateMode.OnValidation, "00/00/00", "MM/dd/yy");
this.startDateMaskedTextBox.DataBindings.Add(b);

Frankly, I'd be happy with 00/00/00 or even an empty string; I can check it
before storing it back to the database if I need to. I just want my user to
be able to blank out the field if (s)he wants to, but also be able to use
the masking so they don't have to enter the slashes.

Also, did the Autotab feature that was in VB6 with the Masked Edit Control
not get carried into the one in .Net 2.0?

I'd greatly appreciate any help you can give me. At this point, I'm ready
to go back to regular textboxes and just tell the user I can't implement it
the way it was in his VB6 application (how appalling!).

Thanks,
Robin S.

djordje
4/16/2007 6:12:16 AM
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 =3D new ContextMenu();
//cm.Popup +=3D new EventHandler(cm_Popup);
//this.ContextMenu =3D cm;
this.MouseUp +=3D new MouseEventHandler(DTextBox_MouseUp);
this.GotFocus +=3D new EventHandler(DTextBox_GotFocus);
this.LostFocus +=3D new EventHandler(DTextBox_LostFocus);
}


#region ------ BackColorActive ----------

private bool prviPut =3D true;
private Color originalBackColor;

private Color backColorFocused =3D Color.White;

[Browsable(true)]
[Category("Appearance")]
[Description("The background color when the component has
focus.")]
public Color BackColorFocused
{
get { return backColorFocused; }
set { backColorFocused =3D value; }
}

void DTextBox_LostFocus(object sender, EventArgs e)
{
this.BackColor =3D originalBackColor;
}

void DTextBox_GotFocus(object sender, EventArgs e)
{
if (prviPut)
{
originalBackColor =3D this.BackColor;
prviPut =3D false;
}
this.BackColor =3D backColorFocused;
}

#endregion


void cm_Popup(object sender, EventArgs e)
{
prika=9EiDatum();
}

// COMMENT THIS METHOD OUT as it calls a form for which you
don't have the source code
private void prika=9EiDatum()
{
frmDatePicker frm =3D new frmDatePicker();
System.Drawing.Point loc =3D this.Parent.Location;
loc.Offset(this.Location);
loc.Offset(this.Width,0);
frm.Location =3D loc;
frm.DateSelected +=3D delegate(object sndr,
DateRangeEventArgs dee) { this.Text =3D dee.Start.ToShortDateString();
frm.Close(); };
frm.LostFocus +=3D delegate(object sndr, EventArgs eargs)
{ ((Form)sndr).Close(); };
frm.Show();

}

void DTextBox_MouseUp(object sender, MouseEventArgs e)
{

}

private bool _EmptyTextIsDBNull =3D 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 =3D 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 =3D this.DataBindings["Text"];
BindingMemberInfo bmi =3D b.BindingMemberInfo;
string fieldname =3D bmi.BindingField;

BindingSource bs =3D ((BindingSource)b.DataSource);
System.Data.DataRow dr =3D
((System.Data.DataRowView)bs.Current).Row;

string tn =3D
dr.Table.Columns[fieldname].DataType.FullName;
bool an =3D dr.Table.Columns[fieldname].AllowDBNull;

if (tn !=3D "System.DateTime")
{
base.OnValidating(e);
return;
}

// try
// {
//DateTime.Parse(this.Text);
base.OnValidating(e);
//}
//catch
//{
if ((e.Cancel=3D=3Dtrue) && (an))
{
dr[fieldname] =3D System.Convert.DBNull;
base.OnTextChanged(new EventArgs());
bs.ResetBindings(false);

e.Cancel =3D false;
}
//else
//{
// e.Cancel =3D true;
//}

//}

}
catch
{
base.OnValidating(e);
}

}

private void InitializeComponent()
{
this.SuspendLayout();
this.ResumeLayout(false);

}

}
}
RobinS
4/16/2007 12:59:03 PM
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.
-----------------------------------
[quoted text, click to view]
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);

}

}
}

RobinS
4/16/2007 8:05:41 PM
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.
--------------------------------
[quoted text, click to view]

Jay Parzych
4/16/2007 11:07:18 PM
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




[quoted text, click to view]

RobinS
4/23/2007 11:10:19 PM
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.
-----------------------------------
[quoted text, click to view]
AddThis Social Bookmark Button