booler

Hi,

I am having a problem implementing databinding in my .NET 2.0 app. I have a number of controls on a user control (the user control's autovalidate property is set to 'disabled'. I fill in the form fields, and try to save the data. The application calls ValidateChildren() on the user control, and my Validating event handlers fire as expected. But somewhere during this process (while the validating event handlers are running) one of my textboxes loses its value (it's reset to empty string). So, by the time its own validating event handler runs, it fails because this is a required field.

The really odd thing is that if I then try to save this again, everything runs as expected.

This is a sample of the code that adds the databindings to my controls:

Code Snippet

private void CreateControlDataBindings(customBusinessObject b)
{
this._personBindingSource = new BindingSource();
this._personBindingSource.DataSource = b;
this.cboTitles.DataBindings.Clear();
this.cboTitles.DataBindings.Add(new Binding("SelectedValue", this._personBindingSource, "Title", true, DataSourceUpdateMode.OnValidation));
this.txtForename.DataBindings.Clear();
this.txtForename.DataBindings.Add(new Binding("Text", this._personBindingSource, "Forename", true, DataSourceUpdateMode.OnValidation));
//this is thw one which loses its value
this.txtSurname.DataBindings.Clear();
this.txtSurname.DataBindings.Add(new Binding("Text", this._personBindingSource, "Surname", true, DataSourceUpdateMode.OnValidation));
}



And these are my validating event handlers:
Code Snippet

private void cboTitles_Validating(object sender, CancelEventArgs e)
{
e.Cancel = !this._validationManager.ValidateItemSelected(this.cboTitles, "A title is required.");
}

private void txtForename_Validating(object sender, CancelEventArgs e)
{
e.Cancel = !this._validationManager.ValidateNullOrEmpty(this.txtForename, "A forename is required.");
}

private void txtSurname_Validating(object sender, CancelEventArgs e)
{
e.Cancel = !this._validationManager.ValidateNullOrEmpty(this.txtSurname, "A surname is required.");
}



The first two both run as expected (i.e. they don't cancel the event), then somewhere between the 2nd and 3rd handler, the txtSurname text value is reset. I notice a slight pause in the application before this happens- almost as if the application is trying to push some data back to the datasource, and failing for some reason.

The business object I am working with contains both a Forename and Surname property, so the problem is not that it can't write the value back to the property I have bound the control to.

If anyone has any suggestions for how to make this work, I would extremely pleased to hear them, as informing the prospective users that they will have to click the save button twice would not go down terribly well.


Re: Windows Forms Data Controls and Databinding Textbox value lost while validating

booler

I'm going to bump this one as I'm still a little lost.

Some more information though- it is not just the one control that is losing its value- all the bound textboxes which have not yet been validated are being cleared.

I added a few more bound controls to the form, and directly after the forename textbox's validating event, all subsequent bound textboxes are cleared. Strangely enough, though, the forename textbox retains its value.

I tried removing the event handler for the forename textbox's validating event, and by the time it reaches the next validating event handler, the values are still lost. It's like an exception is being swallowed somewhere in the databinding process for some reason.

This really is very strange behaviour, and if anyone can point me in the right direction, or has had a similar issue with databinding, it would be extremely helpful to hear of it.

Adam





Re: Windows Forms Data Controls and Databinding Textbox value lost while validating

booler

OK- problem solved. Kind of...

I simply gave up trying to make this work with DataSourceUpdateMode.OnValidation. I changed the update mode to DataSourceUpdateMode.OnPropertyChanged, and everything behaves normally. Of course, this means that bad data can find its way into my business object as I am validating the fields when the data is saved rather than when the controls lose focus, but I can force the user to correct any errors before persisting the object back to the database so this is not a disaster.

I must say, though, that windows forms databinding leaves a lot to be desired. I don't mind if things don't work as I expect them to, as long as there's an explanation why not. But when .NET quietly swallows an exception somewhere upstream, working out what's going wrong can be very difficult indeed.




Re: Windows Forms Data Controls and Databinding Textbox value lost while validating

pg53

I'm struggling with this very issue right now too. I'm using VB so it's not language-specific.

If I set the form autovalidate to EnableAllowFocusChange, then the validating event fires on the controls and the data in them is moved into the bound object via the property set methods. ie it works as expected. (- This is the workaround I'm going for.)

However, I want the validation to occur when the user clicks 'Save'

If I set the form autovalidate property to Disable, then call ValidateChildren when the user clicks the 'Save' button, then the validating events still fire, but the property-sets are no longer called and the object remains 'empty'

So looks like I manage with validating on each control individually, or give up the struggle to make databinding work. As each version of VB has come out, I've looked at databinding, and discarded it. With VB2005, I thought finally there was a binding mechanism that actually was useable in the real world rather than demos. Maybe I was wrong <sigh>





Re: Windows Forms Data Controls and Databinding Textbox value lost while validating

pg53

This looks like it's a bug in .net. With the form set to autovalidate = diabled, then a call to validatechildren causes validate events on all the controls on the form, but only the first one with changed contents generates a property-set call.

However - once I implemented INotifyPropertyChanged in my object, (even without actually raising the event at all ) everything behaved as it should . . .very strange.