Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should the MVVM ViewModel perform type conversion/validation?

We're just getting into MVVM in WPF.

We have implemented our ViewModels with 'strongly typed' properties (int, double? etc.) that we bind to in the view.

Type conversion works OK, mostly, and so entering data is simple enough. But we run into problems with validation.

If, say, a non-numeric value is entered in a text box bound to a numeric property, the conversion fails, the property is never set, and we never get a chance to provide proper feedback to the user. Worse, the property retains its current value, leading to a mismatch between what's displayed in the view and what's actually in the ViewModel.

All this can be handled with value converters, I know. But I have seen several opinions to the effect that conversion should not be the view's responsibility at all. What is entered in the view are strings, and the conversion, validation etc. should be the ViewModel's responsibility (so the argument goes).

If so, we should rewrite most of the properties on our ViewModels to string, and provide error information through the IErrorInfo interface, for example. It would surely make for simpler, leaner XAML in the view. On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer.

It seems to us these two approaches are fundamentally different, so before we decide, we'd like some informed SO opinions on the matter.

So: should ViewModels expose a simplified, 'text-based' interface to the view and handle conversion internally? Or should ViewModel properties expose the actual data types, leaving such chores to the view to handle?

Update:

Hard to pick a winner here, but I finally landed on one of you who concludes more or less like myself.

Specifically, we have decided to keep the ViewModel properties typed. The main reason for this is the flexibility it affords us in the design of the view, and the power of explicit, declarative conversion/formatting in XAML.

I noticed an assumption with you who will disagree with us in this, that the design of the view is fixed and ready. Hence, no decisions about conversion, formatting etc. need be made in the view. But ours is an agile process, and we haven't got all the nitty gritty detail of the UI figured out on beforehand.

In fact, leaving the details of the UI to be worked out along the way leaves room for creativity and besides, in my opinion, even a meticulously worked out design will always end up morphing throughout the implementation process.

The point of all this is that whereas business rules enforcement certainly belongs in the ViewModel, it seems to us that simple conversion and formatting is a view-thing. It may sound like heresy, but I don't actually think type conversion in the view needs unit testing at all (so long av we unit test the actual type converters).

All in all a great discussion, folks, with well formulated, informed opinions. Thanks.

like image 295
Tor Haugen Avatar asked Aug 26 '09 11:08

Tor Haugen


People also ask

What is the use of ViewModel in MVVM?

The purpose of ViewModel is to encapsulate the data for a UI controller to let the data survive configuration changes. For information about how to load, persist, and manage data across configuration changes, see Saving UI States.

How the model changes could be notified to ViewModel in MVVM?

If you want your Models to alert the ViewModels of changes, they should implement INotifyPropertyChanged, and the ViewModels should subscribe to receive PropertyChange notifications. But typically this is only needed if more than one object will be making changes to the Model's data, which is not usually the case.

Should ViewModel know about view?

In fact - the ViewModel shouldn't care about the View at all. It should simply make data available through properties, and it's up to the View to decide what it will dynamically bind to in the ViewModels. If the ViewModel wants to tell the View something this should occur implicit through Bindings.

Should every view have a ViewModel?

For a best mvvm pattern implementation each view must have the own viewmodel, and don't share anythings with other.


2 Answers

This is a very interesting question and one that I don't feel has a definitive answer, but I'll do my best to throw my thoughts out there.

Looking at the MVVM pattern as I understand it, the point of the ViewModel is to expose the data in a way the View can understand without any assumptions about the way the view is going to use it. For an example let's pretend that we are modelling the speed of a car:

public class CarModel
{
    public int MilesPerHour { get; set; }
}

public class CarViewModel
{
    private CarModel _model;

    public int MilesPerHour
    {
        get { return _model.MilesPerHour; }
        set { _model.MilesPerHour = value; }
    }
}

In the example above I've exposed the property as an int since that is what it is in the model. The disadvantages of this you have listed in your question, but the main advantage is that it gives the creator of the view a valuable piece of information about how to display that data. Remember that we (as the authors of the ViewModel) don't know what the View looks like. By committing to the idea of the data being an int the View can use a textbox or some other control that only accepts numbers (a dial, for example) to display the information. If we say that we are going to format the data in a way that we assume is helpful to the View it takes that important power away from it.

On the other hand we work in real world. We tend to know what the view is. We rarely plug and play different views on top of the same ViewModel and adding the conversion code into the ViewModel is simply easier. I don't think it is right, but that doesn't mean you won't find my production code using it...

Finally (and I'm sure you know this, but for completions sake...) business logic should be done in the ViewModel. If we decide that the car shouldn't go above 70mph then it isn't the responsibility of the view to enforce that. So you'll still end up with some kind of error provider, but at a business rather than display level.


Okay, maybe that wasn't finally....

I wanted to address the comments made by Kent, and my thoughts didn't fit into a comment.

Obviously the primary difference between my and Kent's point of view (as I understand it) is he reads ViewModel to be a Model of the View and I read it to be the thing that exposes the Model to the View. A subtle difference I'll admit, but I think the upshot is that I don't want to remove information that the model provides, even if it makes it easier for the specific view I'm using.

My point of view is based on the assumption that you should be able to swap views out, they should be fleeting things that may change depending on the requirements of screen size, hardware, platform, latency and environment. The interesting twist is that I have never actually needed this functionality, nor seen anything (beyond proof of concept applications) that have ever used it, but if we accept that we won't use it now or at any point in the future, and that each ViewModel will work with one, and only one, View then we may as well go back to putting all the code in the code-behind file and throw the ViewModel out completely - after all, it's so tightly coupled that it may as well be the same class.

Ideally I would like a situation where the ViewModel can say "this value is an int, it will always be an int, and you can display it in anyway that you like. But you can give anything back to me and I'll do my best to make it fit, and if I can't I'll let you know". Basically my MilesPerHour property should have an int getter, but an object setter. That way the views keep all the information I feel they need, but don't have to worry about conversions or validation.

like image 126
Martin Harris Avatar answered Oct 12 '22 21:10

Martin Harris


Absolutely it belongs in the view model, for all the usual reasons, including:

  • Designers own the XAML. Do you want the designers to have to understand and implement the requisite type conversion and validation logic?
  • Testability. Don't you want to validate that your conversion and validation logic is working correctly? It's much harder if it's embedded in the view.

On the other hand, conversion, validation etc. will be less declarative, explicit and flexible, from the point of view of the View designer

I think this is a moot point because the view designer should be responsible for these things. The designer is trying to make the UI look and feel a certain way; it is the developer who implements the business logic, including conversion and validation logic.

like image 8
Kent Boogaart Avatar answered Oct 12 '22 19:10

Kent Boogaart