4

So let's say I have a view model, representing a student. The view model is corresponding to a student model, from which the data comes. What I am struggling with, is how to populate the fields in the view model. Do I simply forward reference the fields from the model (where possible) or do I have actual fields in the view model, which I then populate?

Example A - Forward referencing

public class StudentViewModel
{
    public StudentModel Student { get; set; }

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

    public string LastName
    {
        get { return Student.LastName; }
    }

    // ...and so on
}

Example B - Using actual fields

public class StudentViewModel 
{
    public string FirstName { get; private set; }

    public string LastName { get; private set; }

    public void SetStudentProperties(StudentModel student) 
    {
        FirstName = student.FirstName;
        LastName = student.LastName;
    }
}

So obviously both of these examples are overly simplified and I have left out stuff like INotifyPropertyChanged, but I think you get the point. Are any of my approaches viable, or have I completely misunderstood the intend of view models?

I also considered using the constructor for input, but this makes me struggle with the depency injection framework (I am using Caliburn.Micro).

3
  • 1
    Just bind to Student.FirstName and Student.LastName directly. Jul 9, 2019 at 21:57
  • 1
    A ViewModel which simply displays some data from a datasource would be much different from a ViewModel which presents parts of a Model to the user for editing. So there's no one single approach.
    – Graham
    Aug 2, 2019 at 19:27
  • beware that binding directly to classes that don't implement INotifyPropertyChanged will lead to memory leaks in WPF stackoverflow.com/questions/61772492/…
    – Dtex
    Apr 20 at 10:40

3 Answers 3

0

What problem are you trying to solve by duplicating the StudentModel properties in the StudentViewModel? Adding this type of facade wrapper does nothing except bloat the code base. Just include the StudentModel instance as a (read only) property of the StudentViewModel and bind directly to its properties.

Take a look at my blog posts concerning the division of labour between Model and ViewModel classes.

2
  • 1
    Obviosuly in the real use, there might be some derivative properties. A classic example could be a property for Age, which would be derived from DateOfBirth and only be part of the view model. Jul 3, 2019 at 12:25
  • 1
    My blog posts include a methodology for handling such "non-data" properties.
    – Peregrine
    Jul 3, 2019 at 12:46
0

Focus on Responsibilities.

A view model has a particular job. You've already resolved to depend on the model in order to do that job, but the details of the connection between the two only matter insofar as they support the view model's ability to do what it needs to do.

In your specific examples, one is sensitive to changes in the model and one is not. Will the model change? If so, deciding how or if the viewmodel properties should behave will inform the choice of implementation. If the model won't change, the approaches are effectively identical to a consumer. In that case, focus on other concerns such as simplicity.

0

I favor the "A. Forward referencing."

Its API need not be changed when StudentModel is changed.

With a private getter for the StudentModel though, as otherwise the entire ViewModel becomes moot.

"B. Using actual fields" makes a copy (extra resources) of the StundentModel fields, whether actually used or not. Like depending fields say depending on Student.UsesMensa.

And finally, there are cases when a ViewModel can be the Model itself. Mind, it is a very bad idea to let a customer specified report go against a database Model, as then you tie your database fixed, restricting database changes, and exposing technical fields. But for an internal report the boiler plate code just is senseless; indeed harmful to ease of development. Again it is an other case if in a report the fields are evaluated at run-time: "... ${student.firstname} ...". Then you want some ability to verify all fields used, when StudentModel changes - one way is to have a StudentModelView class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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