Value-Conversion in the ViewModels

Value-Conversion in the ViewModels

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


Luzius posted on Friday, December 11, 2009

I'm currently thinking about the following and I'd like to know what others think about that.

I believe a Model, in this case the CSLA-Business-Objects, should expose it's properties in a type that is most natural and convenient for all code that might access it. For instence I might wanna have a numeric property exposed as a decimal.
The designer of the UI now might decide that he would like to allow shortcuts for the user to enter the value such as '1m' as a shortcut for 1,000,000. Someone needs to parse that value and there might be cases where such a string can't be parsed because it contains errors. Such errors should be shown to the user as any other validation error.

Because such a parsing operation is ultimately a presentation issue, I think it belongs to the presentation layer. What do you think about the following solution:
1) The Model exposes its values in whatever type it thinks appropriate. Of course it still contains all business and validation rules on the property.
2) The ViewModel intercepts any property that needs a conversion. If there is an error while converting the value the conversion method should be able to store it in the ViewModel which would aggregate the errors from the Model and its own. Of course, Properties like IsSavable in the ViewModel also need use the aggregated state of the Model and the ViewModel.
3) The UI binds to the ViewModel.

What do you think about this in general? Do you think something like this would be very complicated to add to the ViewModel or to a derived class of ViewModel? I must admit, I haven't yet completely understood the code in ViewModelBase and ViewModel.

Thanks Luzius

RockfordLhotka replied on Friday, December 11, 2009

The primary challenge is that other things bind to metadata about a bound property.

For example, bind a property to the view, and data binding expects (requires) that the object declaring the property implement IDataErrorInfo to provide validation information.

The PropertyStatus control works the same way, but looks specifically for the BrokenRulesCollection on the object declaring the property.

And if the object is bound to a row in a datagrid, the object must implement IEditableObject to fully participate in the expected binding behaviors.

So if you want to bind to read-write properties declared on the viewmodel, then the viewmodel gets very complex very fast, because it has to implement everything expected by data binding. Or you give up all the data binding goodness like validation notification, change notification and correct in-place editing in a datagrid.

Fortunately XAML defines a mechanism to solve the problem you are talking about - it is called a value converter. A value converter is a parser/formatter that sits between the binding source (your object) and the view, and does exactly what you describe without creating all the work required to create a viewmodel that fully participates in data binding.

Luzius replied on Friday, December 11, 2009

Ok, I see that would be a big struggle to implement.

I know the ValueConverters from WPF, but what about errors that occur during the conversion. How do I display them in the property status? Is that possible?

Thanls Luzius

RockfordLhotka replied on Friday, December 11, 2009

This is a challenge. It is not unique to WPF though - the same issue exists
in Windows Forms fwiw...

I wish I had a good answer, but I'm not sure there really is a good answer.

sergeyb replied on Saturday, December 12, 2009

You could possibly have your converter to pass in some predefined value (constant) that would signify the parsing error to the business object. Then your business object can have a validation rule that knows about that value and puts appropriate error message into ruleArgs.Description. This would be mixing business logic with UI logic a bit, but it would satisfy your requirements.

Sergey Barskiy
Principal Consultant
office: 678.405.0687 | mobile: 404.388.1899

Microsoft Worldwide Partner of the Year | Custom Development Solutions, Technical Innovation

-----Original Message-----
From: Luzius [mailto:cslanet@lhotka.net]
Sent: Friday, December 11, 2009 8:05 PM
To: Sergey Barskiy
Subject: Re: [CSLA .NET] Value-Conversion in the ViewModels

Ok, I see that would be a big struggle to implement.

I know the ValueConverters from WPF, but what about errors that occur during the conversion. How do I display them in the property status? Is that possible?

Thanls Luzius

Luzius replied on Saturday, December 12, 2009

Well, I honestly think that returning a special value is definitively the wrong way. I think that such a solution always fires back in the long run.
I think I'll stick to my old solution where the BO actually parses the value and therefore exposes a string. In the case I need the real type I just expose a second property and perform the extra work to trigger the Rules and fire the PropertyChanged event on the other Property.

simon_may replied on Monday, December 14, 2009

Hi there, I would be inteerested to undeerstand your reasoning here.

I have been using special values to acheive the functionality you are after for some years now. This is in a winforms appllication (which does not have a value converter, I am looking forward to moving to WPF/Silverlight next year) which requires some work in my forms framework. Given that you should only need this type of functionality with numeric types and datetime, both of which provide a Minvalue and Maxvalue special value. Given that you may use one of these to indicate a null in the database as with datetimes the other one is available for the purpose That Sergey suggest.

Just think of the ongoing aggrovation that exposing these properties as strings entails. Mainly having to parse these strings in other code that needs to read them. This is not to mention the additional work that Rocky has pointed out.

As I say I have been using this technique for years witrhout issues arising from using a special value for the validation rule to indicate a bad input string to the ErrorProvider. So just interested in any ideas as to why I might have a nasty shock in store for my in the future

Simon

Luzius replied on Monday, December 14, 2009

Well, I generally think using any valid value as a special value a bad idea. This is just like when we used to encode Exceptions in Return-Values of functions: Anything below 0 indicates an Error.
Coding Min/MaxValue as negative/positive infinity is a border case, in my personal opinion it's not completely clean, but it helps a lot with DBs.

My thoughts during the weekend were going to a different solution for the Problem, but I didn't publish this here yet, because I first wanted to try it out. Well I publish the idea now anyway (no guarantees)
I will create little structs or classes that just contain the real value, a flag and possibly the text that was last parsed.
These objects will be value objects and therefore immutable. I will also implement implicit type conversions to and from the real type and I will implement all needed operators.
Then I will expose this value-object directly in the BO-Property.

This should give me the following possibilities:
1) A value converter can do the parsing and the displaying of the value.
2) If there is a parsing error this can be indicated using the flag
3) A BusinessRule can then generate the Error-Message, even using the string that failed to be parsed.
4) Any other code might just use the property in computations.

Well as I have said, I didn't test that solution yet, I will probably find some time over the Holyday break.

Luzius

simon_may replied on Monday, December 14, 2009

An intersting idea but my feeling it will cost you more in grief than you will recieve in benefits. You are going to give up a lot of databinding convenience. For example, binding datetimes to DateTimePickers and numeric types to NumericUpDown controls and the like.

While your intentions here are laudable I thnk the you are ignoring one of the golden rules of software engineering - KISS.

You have already accepted the use of Max/Min values is a grey area and I think it is very different from your example of error codes. In this case it is just one value.

Unless your probem domain requires the use of the special values, for some reason, you should use them for this purpose, as to do so will keep things far more simple and straight forward than any of your suggested solutions will.

Luzius replied on Monday, December 14, 2009

My hope is that databinding will still work because of the implicit type conversions, but as I said, I couldn't test that yet.

Software engineering is very often about compromises, because the perfect solution either doesn't exist or like in this case is far too hard to do. So it's always also a matter of personal preferences. As I said, I will test my solution and then publish my findings here - so everyone else can then use one of the 3 solutions to the problem:
Use Smart..., use special values or use my solution.

Luzius

mbblum replied on Sunday, December 13, 2009

Another approach is to use the SmartXXX object types. SmartDate is included with CSLA. Other Smart datatypes are available from the CSLA Contrib on Codeplex. I think they have a SmartDecimal.

Copyright (c) Marimer LLC