Wednesday, September 28, 2005
« Nice little VB 2005 enhancement | Main | Windows Forms binding issue: A component... »

This is the conclusion (for now) of the issue with Windows Forms data binding that I discussed in an earlier entry.

 

To recap, the issue occurs in detail forms built using data binding. The current control’s value isn’t refreshed when the user tabs off the control. If the data source (business object or smart DataTable with a partial class) changed the value due to business logic that change is not reflected in the UI, even though the changed value is in the data source.

 

In talking to the data team at Microsoft, it turns out that this is a bug and will likely be fixed in some future service pack. At this late stage of the game however, it won’t be fixed for release of VS 2005.

 

Fortunately they were able to come up with a decent workaround in the meantime. The workaround is done in the UI and involves hooking an event from each Binding object, then in the event handler forcing the current value to be refreshed from the data source.

 

To set this up, add the following code to your form:

 

  Private Sub HookBindings()

 

    For Each ctl As Control In Me.Controls

      For Each b As Binding In ctl.DataBindings

        AddHandler b.BindingComplete, AddressOf ReadBinding

      Next

    Next

 

  End Sub

 

  Private Sub ReadBinding(ByVal sender As Object, _

    ByVal e As BindingCompleteEventArgs)

 

    e.Binding.ReadValue()

 

  End Sub

 

Then just make sure to call HookBindings in your form’s Load event or constructor. Ideally this is the kind of thing you’d do in a base form class, then make all your normal forms just inherit from that base so there’s no extra code in each actual form.

 

The HookBindings method loops through all controls on the form, and all Binding objects for each control. Every Binding object’s BindingComplete event is hooked to the ReadBinding method – making it the event handler for all Binding objects.

 

The ReadBinding method handles all BindingComplete events for the form. Any time that event is raised this method merely forces data binding to read the current value from the data source and refresh the control.

 

Since BindingComplete is raised after the user has tabbed off a control and the binding is “complete”, this refresh of the display value ensures that the current control does actually contain the value from the data source even if the data source changed the value.


Wednesday, September 28, 2005 1:58:22 PM (Central Standard Time, UTC-06:00)
Thanks for chasing this down for everyone.
Brian Russell
Wednesday, September 28, 2005 4:19:28 PM (Central Standard Time, UTC-06:00)
This is a decent solution... Of course this would have to recurse on itself since the form's controls only include its direct children, so if there were any group box's on the form, it's controls would have to be looped as well.

Also, the BindingComplete event is actually fired whenever the data is marshalled to the object via the binding infrastructure and that process is complete... so, this would occur when the control was tabbed off ONLY if the DataSourceUpdateMode was OnValidation, however it is OnPropertyChanged this event occurs anytime the property is changed. I didn't try this code, but I suspect if you were using this method of update on the binding, this method would leave you with the original problem... of course I'd want to try it before I'd be sure... something to watch out for though.

I'm wondering if hooking the ctl.Validated event and looping the bindings and doing a readvalue would be an alternative to this...

Shoddy.

Wednesday, September 28, 2005 7:15:17 PM (Central Standard Time, UTC-06:00)
Good point on the container controls - I'd overlooked that possibility. I think you are right about the Validated event as well - in some ways that might be a safer alternative - either that or just LostFocus.
Wednesday, September 28, 2005 8:41:55 PM (Central Standard Time, UTC-06:00)
Lost focus would be called if you were tabbing through the controls... so that would cause unnecessary reads to occur; with the validating / validated events a change would be necessary... semi-trivial; but in a citrix / terminal service environment... cycles are important :)
Friday, September 30, 2005 12:20:17 PM (Central Standard Time, UTC-06:00)
Do I understand this correctly? DataBinding, which really isn't much more than hooking events between the control and the data source, doesn't work, so we have to manually hook events between the control and the data source? ROFLMAO! You realize one more event hook and you wouldn't need DataBinding at all in the first place?
Daniel Billingsley
Monday, October 03, 2005 9:10:36 AM (Central Standard Time, UTC-06:00)
Well, databinding works quite well if your data container is no more sophisticated than the generic DataTable. All the problems I've encountered occur because I'm moving the business logic (validation, calculation, etc.) out of the UI and into the data container (DataTable or business object) - thus creating a logically separate business layer.

While I do find this whole thing rather disappointing, I know for a fact that key people/groups in Microsoft are aware of the issues. Thus I have hope that they'll be addressed as we go forward, making data binding a worthwhile investment for use even today.
Tuesday, October 04, 2005 10:15:52 AM (Central Standard Time, UTC-06:00)
I still say "If you want it done right, you have to do it yourself." Databinding has never worked properly. Just feed the controls yourself, then you'll know what to expect.
Mark Bonafe
Wednesday, October 05, 2005 4:56:40 AM (Central Standard Time, UTC-06:00)
hey Rocky,

Thanks for the tip !! I tried it on an earlier build and got a stack overflow, but on more recent builds it looks like they fixed that recursion issue.
Anyway, you inspired me to make it a zero code implementation... just drag and drop a component onto a form that provides an extender for any BindingSource component (I can picture Billy smiling right now)

http://msmvps.com/bill/archive/2005/10/05/69012.aspx
Comments are closed.