3

So I have started reading some books and articles on architecture. They all state (put a little simply) that you should never let your view access the model directly, when using a Model-View-ViewModel (MVVM) pattern. Instead there should be a view model for each model.

One of the ideas is, as I understand it, that formatting can be done in the view model, which will then mainly contain strings. An example could be a person model which looks like this:

class PersonModel
{
    public string FullName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public decimal YearlyIncome { get; set; }
}

Now a read only view model, could then look something like this:

class PersonViewModel
{
    private PersonModel _person;

    public PersonViewModel(PersonModel person)
    {
        _person = person;
    }

    public string FirstName 
    {
        get { return _person.FirstName; }
    }

    public string DateOfBirth 
    {
        get { return _person.DateOfBirth.ToString("dd.MM.yyyy"); }
    }

    public string YearlyIncome
    {
        get { return _person.YearlyIncome.ToString("N2"); }
    }
}

Now this approach is quite nice, since you don't need to consider string formats in something like XAML (if you are using WPF) or whatever GUI stuff you are working with.

But here is my question; what do I do with the setters using this approach? They obviously need the same input type (string) as the getter, at least when using C# with WPF. I could of course make a custom setter, like this:

public string DateOfBirth
{
    get { return _person.DateOfBirth.ToString("dd.MM.yyyy"); }
    set { _person.DateOfBirth = DateTime.Parse(value); }
}

Is this a viable approach or am I way off, in my understanding of how to use view models?

3
  • Is there a reason you don't just leave the setters off or private, like with your PersonViewModel example above?
    – Shelby115
    May 15, 2019 at 19:01
  • @Shelby115, in case I am working with a form (e.g. for creating a new person), I need to bind the input controls to something. For example, there would be a TextBox with binding to FirstName. And maybe a DateTimePicker with binding to DateOfBirth. May 15, 2019 at 19:04
  • 1
    In that case it would seem your options are parse the string or more common (and better imo) would be to keep your view models plain like your PersonModel. Go ahead and keep things like DateOfBirth a string and format it in whatever is converting from PersonModel to PersonViewModel.
    – Shelby115
    May 15, 2019 at 19:06

1 Answer 1

3

A broader take on the question. Comparison between two approaches to value conversion:

  • Discrete value converter objects, which are declared in XAML. The data types of the ViewModel's properties don't need to match the data types of the corresponding controls in the View.

The architectural advantage of this approach is that property exposed by the ViewModel is decoupled from its corresponding control. As a result, you can change the control in the View without having to change the ViewModel. For example, the ViewModel exposes an integer property, the View can present it as a slider or as a text box, the ViewModel doesn't need to know which kind of control it is.

The downside of this approach is that lots of value converter classes may need to be created. (Similar thing with validation rule classes, which would handle gracefully cases when somebody types "30a" for an integer.) You may be able to reuse value converter and validation rule classes.

  • The ViewModel does value conversion in its getters and setters. The data types of the ViewModel's properties match the corresponding raw data types in the View. This approach has been summarized as "ViewModel is basically a value converter on steroids [from discussion here]."

The advantage of this approach is its flexibility. Once you have the information (in its raw form) in the ViewModel, the binding framework will not be driving your design choices.

The downside of this approach is that the View is more tightly coupled with the ViewModel. (The View presets an integer quantity as a text box which is bound to a string property on the ViewModel. You want to change the presentation to a slider. You will need to change the ViewModel property to a double.) It may or may not be serious issue, depending on the project.

It should be possible to mix these two approaches too, by the way. Some properties may be converted with value converters, others may be converted in getters and setters.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.