Handling Property Changes Within The UI

Handling Property Changes Within The UI

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


NickTaylor posted on Monday, August 02, 2010

Hi,

I wonder if anyone could offer me some advice on this please:-

I have an issue in relation to Windows Forms data binding and some of my business object properties. Following Rocky's expert advice in the past I use a binding source and bound fields to communicate between the UI and my business object. All changes go through the bindingsource and everything works just fine.

However I'm finding a number of scenarios which require the business object to make changes to a number of properties when a specific property value changes. So when property "A" changes, I need to dome some business logic stuff in the BO, and then update property "B", "C", and "D" accordingly. What I am not clear about is how I update the bindingsource properly to reflect the changes that the BO has made to properties "B", "C", and "D" ?

In some cases the BO's have public methods which can be called from the UI and which perform complex business logic actions on the BO resulting in multiple changes to the BO's properties.

It seems the bindingsource is not fully aware of the changes and if the user then tries to undo the editing session, the BO remains dirty and does not revert the changes to properties "B", "C", and "D".

I'm not sure of the correct protocol for handling this type of scenario ?

With many thanks,

Nick

 

JonnyBee replied on Monday, August 02, 2010

Hi,

Are you using the BindingSourceRefresh component in CSLA in your Form?

I prefer to create a custom BusinessRule that does the complex logic and updated the properties.
So long as the properties raise the PropertyHasChanged event in the BO the UI will be updated accordingly. IE: you should not need to write any code for the bindingsource.

How do you handle undo?  Is it the default undo in a WindowsForms control or do you call UndoChanges manually?

If you call UndoChanges manually you must first disconnect BindingSource and BO, call CancelChanges+BeginEdit and then rebind and everything should be fine.

 

NickTaylor replied on Monday, August 02, 2010

Hi...

The first answer is "no". I presume I should be using this right !?

Would you be kind enough to expand slightly on your use of business rules please? I use validation rules for ensuring that user input is valid, but I am not sure how you are implementing a business rule in this type of scenario? I currently have a bunch of public methods on the BO that I can be called from the UI to instigate whatever business logic operation I am trying to perform. Does this approach seem logical to you?

I had a number of exchanges with Rocky regarding handling undo, and managing the UI properly. At present I just call the CancelEdit() method on the binding source. This works fine in a simple form where all changing properties are bound to textboxes on the UI, but in this case its not right. I hope the use of CancelEdit() is right, but please feel free to point me in the right direction if its not!

The other approach was just to reinstantiate the business object and then rebind the bindingsource, but I felt this wasn't quite the right procedure.

Thanks,

Nick

JonnyBee replied on Monday, August 02, 2010

Hi,

You should NOT call CancelEdit on the BindingSource !!!!

If you really want to use N-level undo you should:

  1. Call root.BeginEdit() first.
  2. Bind business objects to UI (bindingsource)
    1. NameValueLists first
    2. Root object
    3. Child object
    4. GrandChild objects

When you want to undo changes your BO should not be connected to the UI so:

  1. Unbind in reverse order from above
  2. Call root.CancelEdit()
  3. Call root.BeginEdit()
  4. Bind business objects to UI (bindingsources)

The sequence of bindingsources in Bind/Unbind is critical !!

I usually have 2 methods in all my Forms:

BundUI() (BeginEdit and connects BO to bindingsources)
UnbindUI(bool cancel)  (disconnect BO and bindingsorces and call ApplyEdit or CancelEdit based on parameter cancel).

When you call CancelEdit on the bindingsource you only try to cancel the last change in a control (the active databinding on a control). Usually this will do nothing as a Button will typically have "CausesValidation=true"  which in turn triggers databinding to update the value in the previous control - so there is nothing to cancel when the call is made.

I highly recommend that you read the DataBinding FAQ and DataGridView FAQ on WindowsClient.net

ValidationRules/BusinessRules can do calculations and set properties the BusinessObject (and you may even add tests so that the rule only does calculations when they are executed on the logical clientside) and when PropertyHasChanged event is raised the UI will auomatically be updated by DataBinding.

NickTaylor replied on Monday, August 02, 2010

Ah, I see, thanks Jonny...

I'll have a play around with the code, and also read the two articles suggested.

Many thanks for your response and your help...

Nick

NickTaylor replied on Monday, August 02, 2010

Jonny,

I quick implementation of your suggestion has cured the problem. Thank you.

The key was obviously in the disconnection and reconnection of the BO and the process of using CancelEdit() and BeginEdit().

Thanks again for your input.

Nick

lukky replied on Monday, August 02, 2010

Hi Nick,

Windows Forms Data Binding relies on thje INotifyPropertyChanged interface to update bound controls, and CSLA BOs implement this interface.

Your UI should update automagically when you update a property on your BO, but only if you fire the PropertyChanged event, which is done for you if you use CSLA PropertyInfo as the backing store for your property.

There is one exception (and workaround), it's when your code modifies the property that's currently being edited. There's a glitch in Windows Forms binding that prevent refreshing the edited value. For example, if you're editing property A, and in your property setter you have logic that modifies A, then the UI will not see it. You need to use the BindingSourceRefresh component on your form.

Have fun :-)

NickTaylor replied on Monday, August 02, 2010

Hi Luc,

I am doing something wrong somewhere, so I need to work through my code again. Typically my BO properties are defined as follows:-

 

 

 

 

 

 

 

// PartNumber

 

 

private static PropertyInfo<string> PartNumberProperty =

RegisterProperty(

new PropertyInfo<string>("PartNumber", "PartNumber"));

 

 

public string

PartNumber

{

 

 

get { return GetProperty(PartNumberProperty); }

 

 

set { SetProperty(PartNumberProperty, value); }

}

 

So these should fire the property changed event right?

Nick

Copyright (c) Marimer LLC