Object Oriented VS. Data Binding.

Object Oriented VS. Data Binding.

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


AAKLebanon posted on Thursday, February 01, 2007

Let's say that i have an OrderDetails object, that is composed of OrderDetail objects. Each OrderDetail object(that is an Editable Child) have a Price field of type Money.

Money is a normal class that hold an Amount field of type integer...

I think that this is a normal object oriented design ! Money encapsulate different thinks related to money:Amount,Currency ... and it have a clear responsibility:Converting from currency to another for example, And (or) formating the Amount value to a string value...

Now the problem is in data binding. I can't bind any control to this field. the TextBox control for example require a field of a primitive type(integer,double,string...).

I am now obliged to create a new control that accept a Money object (the same problem exist with DataGridView). or I am obliged to create 2 properties in the OrderDetail object, one of type Decimal, and the other of type Money, so when the value of the first property change, the second property also change. and this is not a good design. the same problem exist when I try to fetch the Money property value from the DataBase. it is persisted as a Decimal data type, so I am obliged to create 2 properties, one is Private and of Decimal data type, and the other is public of Money data type. when the first change, the second automatically change ... ( I am obliged to use this technic because I use an object persistence framework...).

so what I should do in this situation, what is the best solution, specially when i think that CSLA is about creating "Data Collector Objects", that is, an object that is responsible to collect data and valiadte it( it is similar to DataSet !), so CSLA always deal with data binding...

 

Sorry for my bad english...

malloc1024 replied on Thursday, February 01, 2007

You could try to wrap your OrderDetail object in a façade that would flatten your design.  This would make binding easier.

pelinville replied on Thursday, February 01, 2007

And here is a definition of the pattern malloc speaks of.
 
http://www.dofactory.com/Patterns/PatternFacade.aspx

AAKLebanon replied on Thursday, February 01, 2007

I think this is not the solution, because if I create an object that wrap my OrderDetail object, I will not benefit from CSLA features at all ! for example, broken rules will not be able to show an error icon near of a TextBox, because the broken rule is in OrderDetail and not in the new object.

ajj3085 replied on Friday, February 02, 2007

Your facade could be a BO as well, and you wouldn't lose any of the benefits.

hurcane replied on Thursday, February 01, 2007

We have two "money" objects in our system. As you described, money has a currency and an amount property (e.g 3 Yen, 2 US Dollars, etc.). We also have a MoneyUnit, which also includes a unit of measure (UOM). This is used for unit pricing and costing (e.g. 2 US Dollars per square meter, 3 Yen "each", etc.), and it handles conversions between compatible units of measure.

These objects are mostly kept inside business objects. Maintenance UIs want to provide separate fields for these properties. The two straightforward techniques are to expose the money object to the UI or to present simple data types and use the setters on the business object to keep the internal money objects in sync. Exposing the money object makes the business object simpler, but makes the UI more complex because it has to handle binding multiple objects and keeping the binding relationships in sync. Exposing the simple fields makes the UI simpler, but it means putting code in the busines object to keep the Money objects in sync.

The decision really depends on the use case. In our system, an order line has a price and a cost, both of which are money units. The order entry use cases dictates that the UOM property of price and cost are always the same (currency is defined at the order level, which is a different design problem). The user only wants to fill in three fields. This requirement led us to the obvious decision that we should map the fields in the object.

In another use case, where there is only a single money amount being edited, the choice is not as clear. We found that  the majority of our use cases involving money had requirements similar to the order entry use case. We have chosen to standardize on this technique (exposing only simple data types) when the design choice is not clear.

SonOfPirate replied on Friday, February 02, 2007

Maybe I'm missing something in the discussion, but I have many custom value types (structs) defined in our framework, Currency being one of them.  I do not have a problem databinding to properties of these types.

Only thing I can think of causing a problem is if you have not overriden the ToString() method.  All of my value types implement IConvertible, override ToString and have an implicit conversion to string that delegates to the ToString method.  Maybe your problem lies somewhere in here.

HTH

 

jupp replied on Friday, February 02, 2007

I think you should implement a ICustomTypeDescriptor on your Detail class. For details please visit.

http://msdn.microsoft.com/msdnmag/issues/05/04/NETMatters/
http://msdn.microsoft.com/msdnmag/issues/05/05/NETMatters/

For a collection of Details you could implement ITypeList

 

AAKLebanon replied on Monday, February 05, 2007

thinks for all the participants in this discussion and i found the solution.

Simply a create a MoneyConverter class that inherits from TypeConverter:

Public Class MoneyConverter

Inherits System.ComponentModel.TypeConverter

Public Overrides Function CanConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal sourceType As System.Type) As Boolean

Debug.WriteLine("CanConvertFrom " & sourceType.ToString)

Return sourceType Is GetType(String)

End Function

Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean

Debug.WriteLine("CanConvertTo " & destinationType.ToString)

Return destinationType Is GetType(String)

End Function

Public Overrides Function ConvertFrom(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object) As Object

Debug.WriteLine("ConvertFrom " & value.ToString)

Return New Money(value.ToString)

End Function

Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object

Debug.WriteLine("ConvertTo " & value.ToString & "(" & destinationType.ToString & ")")

Return value.ToString

End Function

End Class

Now i will decorate my Money class with this attribute:

<System.ComponentModel.TypeConverter(GetType(MoneyConverter))>

I have tested this in a DataGridView and it is worked fine !!

Think's again and good luck...

Copyright (c) Marimer LLC