WinForm Binding Issue and Issue with Slowness during Apply and Cancel Edit

WinForm Binding Issue and Issue with Slowness during Apply and Cancel Edit

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


KickTheSky posted on Wednesday, March 26, 2008

I am having two issues.

The first one involves binding to WinForms.  When I bind my fields there are times where the last changed field never gets updated in binding when the save button is clicked.  Is there any way to force binding to update the business object before the save?  For example, the last field on the form is a phone number field, if you enter the data into that field and don't tab out of it, it does not update the binding when you hit the save button.

Along with that issue, is it possible to update binding on change rather than on lost focus?  Is it something that will slow down my app?

The second issue has to do with speed of apply and cancel edits.  It seems that the speed of which these are occuring is taking more than 5 seconds at time for a simple object with only one child object.  The object I am representing is an Organization and an Organization has an Address.  The Address is stored in a different component because it is a utility object used for Customers and Vendors and other objects.  Organizations have only one address, so it is a single child.  Also, the Address fields are stored in a seperate user control, also stored in a different component.  This address control is then dropped onto the main Organization control to provide the address.  Is it all of the cross component communication that is slowing everything down?  Thanks for any insight which you can provide.

triplea replied on Wednesday, March 26, 2008

Regsrding your first issue, expand your (DataBindings) property of your control (whatever it is) and click on the "..." button in the Advanced field. In there, depending on where you are binding (i.e for a textbox it would be Text, for a combobox it would be SelectedValue etc) change the DataSourceUpdate mode from OnValidation to OnPropertyChange.

Regarding your second issue, are you overriding the OnPropertyChanged method? Also are you specifying the property name in your PropertyHasChanged, CanReadProperty, CanWriteProperty calls within your properties?

tetranz replied on Wednesday, March 26, 2008

KickTheSky:
I am having two issues.
The first one involves binding to WinForms.  When I bind my fields there are times where the last changed field never gets updated in binding when the save button is clicked.  Is there any way to force binding to update the business object before the save?

Is the save button on a toolbar? I've noticed that toolbar buttons don't make the form validate. You can always called the form's Validate() method in the button click event. If save is a normal button then I don't know why this is happening for you.


Along with that issue, is it possible to update binding on change rather than on lost focus?  Is it something that will slow down my app?

triplea showed the way but you probably don't want it for all controls. I don't think it's a good idea for textboxes because you'll be refreshing the form on every keystroke.  I set it to OnPropertyChange for things like checkboxes etc which are "instant change" sort of things.


The second issue has to do with speed of apply and cancel edits.  It seems that the speed of which these are occuring is taking more than 5 seconds at time for a simple object with only one child object.  The object I am representing is an Organization and an Organization has an Address.  The Address is stored in a different component because it is a utility object used for Customers and Vendors and other objects.  Organizations have only one address, so it is a single child.  Also, the Address fields are stored in a seperate user control, also stored in a different component.  This address control is then dropped onto the main Organization control to provide the address.  Is it all of the cross component communication that is slowing everything down?  Thanks for any insight which you can provide.

I think you need to isolate this a little further. What if your objects are not bound to the UI? If you run some test code that calls BeginEdit(), changes a property or two and then calls CancelEdit(), does the cancel still take a long time? i.e, Is it really related to binding? I struck this sort of slowness in two ways long ago. One was that I was binding my buttons' enable properties to the BO, IsValid and IsDirty etc properties so that they are only enabled at appropriate times. That never worked smoothly for me.  I followed Rocky's suggestion on his site somewhere (going back a year or two now) which updates button states in the bindingSource CurrentItemChanged.  The other slowness was caused by effectively having circular references in my objects. If you have a collection item that has a reference to it's parent, then you should mark that parent reference as [NotUndoable()].

I don't know if any of that applies to you.

Cheers
Ross

KickTheSky replied on Wednesday, March 26, 2008

The save button is indeed on a toolbar.  I will work a validate call into the base windows control I have that uses the toolbar.  Thanks to both of you for pointing out the way to change the binding behavior.

As for the second issue, all properties do indeed reference the property name in the PropertyHasChanged calls.  I do not include parent references in any of my children.  I pass the parent into persistance calls so that it gets persisted to the proper parent in the database.  I have been changing my button states right in the OnPropertyChanged event handler.

I will revisit my unit testing to see if the problem is occuring in the objects first and report back my findings.

Thanks for the help!

AzStan replied on Wednesday, March 26, 2008

Data binding can cause a bunch of performance problems if your object remains bound to the UI while persisting your business objects.  Rocky has taught some best practices regarding unbinding your objects from the UI and cloning the object before saving it. Unbinding is trickier than you might hope.

At very least, check to see that you are setting RaiseListChangedEvents=false on your binding source before calling save.

KickTheSky replied on Wednesday, April 02, 2008

Okay, it looks like the issue is in the binding.  I ran seperate NUnit tests on the business objects to add, save, load, change, save, and delete and had nearly instant response time.  When the objects get bound, however, that is when the issue occurs.  I am looking at load times near 10 seconds and save times that are even longer.  When I stop in the debugger it is cycling through the serialization code.  I am doing the RaiseListChangedEvents and cloning on the save.  Anything else I might be missing on the binding that is slowing it down?

Oh, one other note.  I did a proof of concept app and did not run into these problems.  The entire UI was contained in an executable.  This time, there are seperate controls, one for base controls (WinPart, EditWinPart), one for each part of the business (Customer, Inventory, Accounting), and then one for the UI shell, which is the executable.  The EditWinPart is being used, which is inheriting WinPart and adds a pick list on the left hand side of the form and then on the right hand of the form goes the form data.  It also includes a toolbar for add/update/delete and save/cancel/close based on the state of the form.  When I did the prototype I had the pick lists seperated out onto a pop-up form and on this they are on the form with the other data and disabled while the person is editing their data.

Copyright (c) Marimer LLC