Nested BO's, Business Rules, BindingSources and ErrorProviders

Nested BO's, Business Rules, BindingSources and ErrorProviders

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


cultofluna posted on Wednesday, January 03, 2007

I have a problem with nesting BO's and using errorproviders to show problems in the GUI. To make the situation a little easier to explain I'll use two BO's in my example.

Housenumber Addition BO

This BO validates the structure of an Housenumber Addition value when it's assigned. The BO has no rules for the value being required or optional.

Address BO

This BO validaties information for an Address. The Address consists of two values: a streetname (string) and a housenumber addition (pobox).
The housenumber addition is optional by default, however when the streetname matches the value "P.O. Box" the housenumber addition may never contain a value.

TestApplication

The TestApplication consists out of a form containing two textboxes, a bindingsource and an errorprovider.

The bindingsource datasource is connected to an instance of Address. The errorprovider datasource is connected to the bindingsource. The two textboxes are bound to the streetname and the housenumber addition.

The problem

When I enter the value "P.O. Box" in the street textbox, the errorprovider shows an error icon next to the housenumber addition textbox with the message that a value is not allowed. So this works perfectly.

Next when the street textbox contains another value, for example "street"
, the error icon for the housenumber addition dissappears. However when I enter a value for the housenumber addition that is validated as being incorrect (by it's own BO!) the error provider doesn't do anything!

I have already tried binding to the housenumber addition BO instead. However, now the "P.O. Box" validation doesn't work anymore!

I can understand that the errorprovider only supports one bindingsource, but this makes the use of nesting BO's (and their validation) impossible for use with a GUI!

Does anybody regconize this problem or perhaps have a solution for it?


simon_may replied on Tuesday, December 04, 2007

I have recently experienced the same issue. I see there were no answers forthcoming to this particular post. Maybe it has been answered in another thread but I have been unable to find it.

I am keen to be able to use nested objects for a number of reasons. So all i need to know is wherher the current ErrorProvider will work in this situation or do i need to flatten out my business object.

I'd appreciate any guidance

ajj3085 replied on Tuesday, December 04, 2007

One possible solution may be to expose the properties of the address via the root Bo.  You wouldn't expose the address object directly.  You can then override IDataError in the root BO to return the error strings from the contained address object.

HTH
Andy

simon_may replied on Tuesday, December 04, 2007

hi Andy

Thanks for the reply. I cannot find a way to override IDataErrorInfo. Complaint is that the Root BO does not implement IDataErrorInfo. Which i find puzzling as Core.BusinessBase declares and implements it. My knowledge of rules governing what can and cant be seen in descendant classes is lacking somewhat. Any ideas?

ajj3085 replied on Tuesday, December 04, 2007

Sorry... you wouldn't override it, you'd implement the interface explicitly on your root BO.  BusinessBase also implements it explicitly; your explicit implementation will hide the base classes implementation.

simon_may replied on Tuesday, December 04, 2007

Pretty much as i thought it was done but obviously messed up somewhere the first time I tried. I now have it working but after putting a breakpoint in discover that it is only asked for errors relating to Root BO properties only. I Suspect that the problem lies with ErrorProvider and Binding Source.

Ill have to flatten out the business object.

Thanks

simon_may replied on Wednesday, December 05, 2007

Of course it would help if I read all your advice. Forgot to expose the contained objects properties as the root BOs own. I can now move on. Thank goodness for Code gen makes these changes easier.

BeGreen replied on Tuesday, June 17, 2008

Hello,

I see from this post that you have found a solution to this issue which  is, showing errors on Error Providers when they are bound to Nested Business Objects.

I havent been able to figure out how to expose the nested object's properties as the root BO's own.

In my case, I have a BusinessObject class which implements iDataErrorInfo and  INotifyPropertChanged.All my objects derive from BusinessObject and these objects in turn, may contain each other. eg, Customer and Address both derive from BusinessObject.Customer has a property of type Address. How do I implement IDataErrorInfo and INotifyPropertChanged (these are implemented in BusinessObject) .

Appreciate any pointers,suggestions.

 

Thanks

 

 

 

 

 

 

 

simon_may replied on Wednesday, June 18, 2008

Hi. I am not sure that I understand exactly what you are doing here. 'Customer and Address both derive from BusinessObject.Customer has a property of type Address' does not make sense to me if you are using CLSA in the convenrional manner, i.e. the use of the generic BusinessBase class.

However, to answer your question. I'll warn your that it is not pretty expecially if you hand craft your business objects. 

The outer object (eg Customer) exposes the inner object's (eg Address) properties as its own and delegates calls to them. The outer object containsa static list of inner object property names  The outer object explicitly implements IDataErrorInfo.this[string propName] and IDataErrorInfo.Error. The IDataErrorInfo property getter checks static list of Inner object property names and if present delegates to the inner object's IDataErrorInfo.this property. If the property does not belong to the inner object it handles the call by returning the its  ValidationRules.GetBrokenRules().GetFirstBrokenRule(propName).Description.

I have to say the only reason I live with this solution is that I have my own application generator that knows about contained or inner objects and generates hte outer object delegating properties and  the inner object  property name list. In fact I go a bit further in that I can handle multiple inner objects, so the static list is actually a dictionary which maps the property to its correct inner object.  

IDataErrorInfo.Error returns a concatenation of all BrokenRules in the outer inad inner objects very much as BusinessBase does

I hope that helps

BeGreen replied on Wednesday, June 18, 2008

Hello Simon_may,

Thanks for the detailed reply.
I did suspect that the only way for me to expose the nested object's properties as the Container/Outer,(not root) object's property is to explicitly define them.

"The outer object (eg Customer) exposes the inner object's (eg Address) properties as its own and delegates calls to them. The outer object containsa static list of inner object property names "

As I mentioned earlier, I have defined a BusinessObject class(not CSLA.BusinessBase) which implements 
        IDataEntity,
        INotifyPropertyChanged,
        IDataErrorInfo

All my business objects like Customer,Person,Name,Address etc derive from BusinessObject. And these may in turn contain each other. Like Customer has Person and Address.Person has Name and a date field.And so on..
All these are in turn contained in an object named "Universal". So,this has multiple,complex and more than 4 levels of nesting.One object might be part of multiple outer objects. (eg , Name will be contained by Customer,Contacts,Friends,etc).
I am binding "Universal" as binding source to the UI and to the ErrorProviders. So whenever there are errors on Name or Address, ErrorProvider  does not show.

Now, BusinessObject implements IDataErrorInfo and iNotifyProperty changed.With our present architecture, I cannot implement these in the outer objects (eg customer).Like you, I do have a list which keeps tract of the errors associated with the Objects and they come up correctly when I iterate through the list. But this doesnt help the ErrorProvider.

 I probably need to be able to get a reference to OuterObject from the current instance(of the child object) at runtime. I am going down the nesting, but need to go up and somehow assign the error to the parent object. This has to recursive as there are multiple nesting levels.

I hope there is a better and simple way of doing this.

I am going through JohnB's sample now and hope to see light.

Again,any pointers highly appreciated.

Thanks

 

 


 

JohnB replied on Wednesday, June 18, 2008

BeGreen,

Not exactly sure if this is something you're looking for but I posted an example of working with broken rules for nested business objects. Check it out and hopefully it helps.

John

BeGreen replied on Wednesday, June 18, 2008

Thanks JohnB.

This definitely gives me a lead to work on.

 

jpm replied on Monday, December 14, 2009

it seems easier to me to change the error providers data source as you enter and leave controls that are bound to child business objects.

Copyright (c) Marimer LLC