Data binding in Win forms

Data binding in Win forms

Old forum URL: forums.lhotka.net/forums/t/3394.aspx


rossl123 posted on Friday, August 17, 2007

I have a problem that I am wondering if anyone in the CSLA community has come across.

My winforms controls behave strangely if I code against their 'changed' events, they don't seem to invoke the binding mechanism on the first time through.

To elaborate, my users were getting irritated by the fact that a form is not dirtied until they leave a control. Consequently, on forms with say just a single enabled data control (like a text box), they cannot click on the 'Save' button immediately after making a value change because the Save control doesn't get enabled until the focus has left the text box. So the Save button cannot be clicked on until the user clicks another active control first, or tabs away from the textbox control.

To get around this problem I trapped the 'changed' event on the text box control and invoked the form ValidateChildren() method. This allows the content of the control to be 'committed' which in turn invokes the binder to the underlying business object, which dirties the form and enables the 'Save' button. It also has the added side benefit of allowing instant feedback for things like keystroke level validation.

What I have experienced is that everything works wonderfully well, except on the very first control 'changed' event (this occurs not only for textboxes). Even if that event is to paste multiple characters into the control, everything works as you would expect, except the binder mechanism doesn't get fired off and the underlying business object doesn't get the bound controls properties set, so the form doesn't get dirtied. Any subsequent change works as expected, it's just the first one, and even then it's just the first one after the form is shown and the control receives the focus for the first time.

What I am describing sounds very much like a problem with .Net, and I will be posting to the MSDN user goups as well, but I thought perhaps I might have a better chance of striking a chord with someone here first.

Cheers
Ross

triplea replied on Friday, August 17, 2007

Well indeed this isn't a problem of CSLA as such but rather in the way databinding works (I wouldn't even call it a problem for databinding...). The problem you have is that you want the Save button to get enabled directly when the user types something in a checkbox, changes a selection in a combo etc. I never use this functionality, leaving the save button always enabled and leave the bo save only if the object is dirty. Furthermore, all my forms (or user controls rather) know that when they are initiating a save and specifically change focus in order to complete the change.
Back to your problem. I guess a one way of enabling your save button is to create custom controls for your textbox, combobox etc which have a Button property. Then internally, if a change occurs (and before databinding kicks in) you can enable that button. The only problem is that if e.g. you paste something in a textbox (and the event fires to enable the save button), then delete everything, you will need to be smart about disabling the save button again.
Maybe I am overcomplicating this though...

tetranz replied on Friday, August 17, 2007

Hi Ross

There is a standard way of doing what you want by changing one of the databinding properties. I'm doing this from memory so I might not have the words exactly right but on the properties of a control in Visual Studio, expand "Databinding" near the top and then hit "Advanced". You can change when validation occurs from OnValidation to OnPropertyChanged. I think that will achieve what you're doing with the changed event.

I always do that for clickable type controls such as checkboxes or dropdown lists but I don't usually do it for textboxes. I think it would mean a lot of activity for every keystroke but ... its probably not an issue.

The user usually wants to close the form after saving so I solve the problem you're dealing with by trapping the FormClosing event and prompting with a "Do you want to Save". That works fairly well, it means that the user hits the close button instead of Save even if Save is disabled. I described it here http://forums.lhotka.net/forums/post/16170.aspx

Cheers from another Ross

richardb replied on Friday, August 17, 2007

As you type in the textbox your Business Object property should be getting set at each keystroke and hopefully the rules checking would be firing too, and the BO would evaluate it's state.  If IsValid is true then doesn't some event get fired by the BO which the WinForm can handle and then enable/disable the buttons?

That's from my memory too as I don't have the code to hand.....we created some base UI forms to do all of this - I'll look back and post how we actually did it once I find it.

triplea replied on Friday, August 17, 2007

tetranz:

You can change when validation occurs from OnValidation to OnPropertyChanged.

richardb:

As you type in the textbox your Business Object property should be getting set at each keystroke and hopefully the rules checking would be firing too, and the BO would evaluate it's state.

I'm not sure if I am getting confused here but that's not the behaviour I see. The property gets changed only once you tab out of a checkbox or combobox... Even if you manage to change databinding settings like tetranz specifies, I still can't see how the save button would become enabled since the propery only changes when the user has tabbed out... An I the only one seeing this behaviour? Confused [8-)]

tetranz replied on Friday, August 17, 2007

triplea:
I'm not sure if I am getting confused here but that's not the behaviour I see. The property gets changed only once you tab out of a checkbox or combobox... Even if you manage to change databinding settings like tetranz specifies, I still can't see how the save button would become enabled since the propery only changes when the user has tabbed out... An I the only one seeing this behaviour? Confused [8-)]


It definitely works for me the instant I click on a checkbox or select from a dropdown list. The BO is updated and the buttons change. That's if I set the "Data Source Update Mode" (I have the words right now) to OnPropertyChanged. If I leave it set to the default which is OnValidation then I get the behaviour you describe which is what I'd expect. It determines when your BO will receive a new value from the UI. The call to PropertyHasChanged() in your property setter will trigger the other magic to happen.  I've never tried a textbox but I think it should work on each keystroke. I'm at home today and don't have a CSLA project to try it on.

I'm not sure how you're controlling the buttons but I strongly recommend following Rocky's advice and control the buttons from the BindingSource CurrentItemChanged event rather than try to bind the enable properties. http://lhotka.net/Article.aspx?area=4&id=5faaee8e-8496-4845-86f7-787c6b64096c

Ross

rossl123 replied on Monday, September 03, 2007

Thankyou all for your replies. Changing the update behaviour using the Data Source Binding Update Mode certainly came as a revelation to me and did help streamline my code. It certainly does work for text boxes and the way I have hooked up my Save and Reset buttons works fine, except in the unusual circumstances that I originally reported.

When the form is first loaded and it's controls bound to the first bo, the OnPropertyChanged event doesn't seem to fire at all for any control on the form until a focus change event occurs where a control has been altered. Once any control on the form has been altered, binding updates at the control changed level work as advertised. Strange. I have multiple instances of this phenomenon, not just one form, although they are all coded using the same design template.

I did have other issues way back with my forms that necessitated implementing code at the Form Enter event (to do with setting properties of controls on the parent form) and it seemed to help stabilise things if I did the databinding for the current bo during this event as well, including that of the initial bo when the form is first loaded. On first load it is interesting to note that the form hasn't actually been properly painted at that stage, maybe that has something to do with it?

Once again, thanks to those who have helped look into this problem.

Copyright (c) Marimer LLC