Parse C # DateTimePicker DataBinding event not working

I have a datetimepicker that I bind to the Date / Time null column in the dataset. I have successfully applied the Format event to null, not null. But, when I remove the dtp control, it does not get null in the dataset. This is my code:

dtpBirthdate.DataBindings.Add(new Binding("Value", bsStaff, "birthDate", true)); dtpBirthdate.DataBindings["Value"].Format += new ConvertEventHandler(dtpFormat); dtpBirthdate.DataBindings["Value"].Parse += new ConvertEventHandler(dtpParse); 

Formatting and parsing events:

 private void dtpFormat(object sender, ConvertEventArgs e) { Binding b = sender as Binding; if(b != null) { DateTimePicker dtp = (b.Control as DateTimePicker); if(dtp != null) { if (e.Value == null || e.Value == DBNull.Value) { dtp.Checked = false; dtp.CustomFormat = " "; e.Value = false; } else { dtp.Checked = true; dtp.CustomFormat = "dd-MMM-yyyy"; dtp.Value = (DateTime) e.Value; } } } } private void dtpParse(object sender, ConvertEventArgs e) { Binding b = sender as Binding; if (b != null) { DateTimePicker dtp = (b.Control as DateTimePicker); if (dtp != null) { if (dtp.Checked == false) { e.Value = DBNull.Value; } else { e.Value = dtp.Value; } } } } 

After debugging, I found that it goes into an endless loop between parsing and formatting events. What is wrong with my code?

Edit: There is also a datagridview bound to the bsStaff binding source.

+7
c # parsing nullable binding datetimepicker
source share
5 answers

You bind the sender as bind before the zero check. check if the sender is zero before casting and you should be fine.

+1
source share

I noticed that you are using data binding event capture for both controls, but in the first dtpFormat event handler, you do not check the data binding values ​​first.

IMHO this line of code:

if (e.Value == null || e.Value == DBNull.Value)

need to change to

if (e.Value == DBNull.Value || e.Value == null)

+1
source share

The problem is that you need to configure e.Value for something; but if you change it, it will start parsing again. Try setting it to its original value.

 e.Value = dtp.Value; 

Here is a link to someone who has come across this before. They did not use your DbNull.Value, but other than that it is almost identical to what you are doing.

http://blogs.interknowlogy.com/2007/01/21/winforms-databinding-datetimepicker-to-a-nullable-type/

+1
source share

The following should fix the problem (see comments in code):

 private void dtpFormat(object sender, ConvertEventArgs e) { Binding b = sender as Binding; if(b != null) { DateTimePicker dtp = (b.Control as DateTimePicker); if (dtp != null) { if (e.Value == null || e.Value == DBNull.Value) { dtp.Checked = false; dtp.CustomFormat = " "; // e.Value = false; // To prevent dtp.Value property setter setting Checked back to true e.Value = dtp.Value; } else { dtp.Checked = true; dtp.CustomFormat = "dd-MMM-yyyy"; //dtp.Value = (DateTime) e.Value; // dtp.Value will be set to e.Value from databinding anyway } } } } private void dtpParse(object sender, ConvertEventArgs e) { Binding b = sender as Binding; if (b != null) { DateTimePicker dtp = (b.Control as DateTimePicker); if (dtp != null) { if (dtp.Checked == false) { e.Value = DBNull.Value; } else { //e.Value = dtp.Value; // Do nothing, e.Value is already populated with dtp.Value } } } } 

But the whole idea is erroneous from the very beginning, because it is based on binding the data binding infrastructure (a typical XY problem is to overcome the lack of the DateTime? Value property in DTP). Convert and Parse events are expected to convert a value from a data source value to a control value and vice versa. They should not read or write control properties (it destroys all encapsulation), information is provided through e.Value and e.DesiredType , and handlers must modify e.Value based on this information.

The right way is to create a custom control that inherits DateTimePicker and implement the (shadow) DateTime? Value property DateTime? Value DateTime? Value The property getter and setter can use the necessary logic (they are allowed to read / modify other properties). Then replace the DTP controls with this custom control and just bind the Value property without any binding event handlers.

Update: The following is a short-term and fuzzy implementation of the aforementioned optional approach:

 public class CustomDateTimePicker : DateTimePicker { public CustomDateTimePicker() { Format = DateTimePickerFormat.Custom; SetValueCore(null); } new public DateTime? Value { get { return Checked ? base.Value : (DateTime?)null; } set { if (Value != value) SetValueCore(value); } } private void SetValueCore(DateTime? value) { if (value == null) Checked = false; else base.Value = value.Value; UpdateCustomFormat(); } protected override void OnValueChanged(EventArgs eventargs) { UpdateCustomFormat(); base.OnValueChanged(eventargs); } private void UpdateCustomFormat() { CustomFormat = Value != null ? "dd-MMM-yyyy" : " "; } } 
+1
source share

dtpParse sets the value e.Value = dbNull.Value, which will cause dtpFormat to fire as the value changes, which in turn sets e.Value = false, which is different from dbNull.Value, which starts dtpParse again. Try removing e.Value = false from dtpFormat

0
source share

All Articles