0

I have spent long time searching about MVVM in WPF. I understand why to use it. This is clear for me. What I don't is, what is in ViewModel itself. I know it is the connection between the View and the Model. Also, I know (at least, what most of programmers suggest) that implement the INotifyPropertyChanged. Adding to this, the Commands.

Let say, that I have this Model (Code First with EF 6):

public class City
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CityId { get; set; }

    [DataType("VarChar"), MaxLength(25), Required]
    public string CityName { get; set; }
}

My Questions are:

1- In many examples I've seen, they recreate the same fields again in VM. What is the purpose, is it enough to have the whole object (City in my example). How about if there are many fields!.

2- To be able, to use it in my View (CRUD), how is the CityVm() will be in my example?.

I appreciate any help.

Dennis
  • 37,026
  • 10
  • 82
  • 150

3 Answers3

4

The view model in the MVVM pattern encapsulates the presentation logic and data for the view. It has no direct reference to the view or any knowledge about the view's specific implementation or type. The view model implements properties and commands to which the view can data bind and notifies the view of any state changes through change notification events. The properties and commands that the view model provides define the functionality to be offered by the UI, but the view determines how that functionality is to be rendered.

The view model is responsible for coordinating the view's interaction with any model classes that are required. Typically, there is a one-to many-relationship between the view model and the model classes. The view model may choose to expose model classes directly to the view so that controls in the view can data bind directly to them. In this case, the model classes will need to be designed to support data binding and the relevant change notification events.

The view model may convert or manipulate model data so that it can be easily consumed by the view. The view model may define additional properties to specifically support the view; these properties would not normally be part of (or cannot be added to) the model. For example, the view model may combine the value of two fields to make it easier for the view to present, or it may calculate the number of characters remaining for input for fields with a maximum length. The view model may also implement data validation logic to ensure data consistency.

The view model may also define logical states the view can use to provide visual changes in the UI. The view may define layout or styling changes that reflect the state of the view model. For example, the view model may define a state that indicates that data is being submitted asynchronously to a web service. The view can display an animation during this state to provide visual feedback to the user.

Typically, the view model will define commands or actions that can be represented in the UI and that the user can invoke. A common example is when the view model provides a Submit command that allows the user submit data to a web service or to a data repository. The view may choose to represent that command with a button so that the user can click the button to submit the data. Typically, when the command becomes unavailable, its associated UI representation becomes disabled. Commands provide a way to encapsulate user actions and to cleanly separate them from their visual representation in the UI.

To summarize, the view model has the following key characteristics:

  • The view model is a non-visual class and does not derive from any WPF base class. It encapsulates the presentation logic required to support a use case or user task in the application. The view model is testable independently of the view and the model.
  • The view model typically does not directly reference the view. It implements properties and commands to which the view can data bind. It notifies the view of any state changes via change notification events via the INotifyPropertyChanged and INotifyCollectionChanged interfaces.
  • The view model coordinates the view's interaction with the model. It may convert or manipulate data so that it can be easily consumed by the view and may implement additional properties that may not be present on the model. It may also implement data validation via the IDataErrorInfo or INotifyDataErrorInfo interfaces.
  • The view model may define logical states that the view can represent visually to the user.
Glen Thomas
  • 10,190
  • 5
  • 33
  • 65
2

This is a pretty broad topic based a lot on opinion. The MVVM model isn't a set-in-stone thing, and there's lots of different ways of implementing it.

The ViewModel, in my opinion, has two main purposes:

1) To expose the Model to the View. There's two ways of doing this. Having your Model wrap your CRUD object and manage NotifyPropertyChange. In this case, it's common for your ViewModel to just expose the Model to the View and not do much else with it, the View binding directly to the Model, or via simple pass-through properties.

The other common scenario is just to have your model as a CRUD. In this case, the ViewModel manages the NotifyPropertyChange notifications and manages model updates, etc.

2) To manage Presentation logic and data. There's lots of things that you need to bind to and store that have no place in the Model. The Model is the data. It's most likely loaded from a database. Yet the View needs to track other properties. An example: say your city object is displayed in a list, and you want to show or hide it with a button. The logic for hiding it, and the boolean for it being hidden doesn't belong in the View, and has nothing to do with the base data in the Model, so it sits in the ViewModel.

Similarly, maybe you have a CityPopulation property. In your view you want to highlight cities that are larger than 1,000,000 population in red. Your View Model has the a property:

bool LargeCity
{
    return CityPopulation<1000000;
}

And you render the label with a style trigger.

Another example, a ViewModel containing a Brush property to bind to, which I think is probably a common but bad practice. slugster also comments below that visual elements should not be present in the ViewModel.

Brush HighlightBrush
{
    get
    {
        if (CityPopulation<1000000)
        {
            return Brushes.Red;
        }
        else
        {
            return Brushes.Black;
        }
}
jscs
  • 63,694
  • 13
  • 151
  • 195
Joe
  • 6,773
  • 2
  • 47
  • 81
  • A Brush is a visual element. Don't put brushes in your viewmodel. It is the VM's job to present a value, and then the View translates (or renders) according to that value. So for this example you would have a flag `IsCityGreaterThanMillion`, the view will then render using the brush appropriate for the true/false values from that property. – slugster Apr 29 '16 at 11:58
  • I think that was just some kind of example of him. Not a specific suggestion to do... – Frerk Morrin Apr 29 '16 at 12:01
  • @FrerkMorrin It was a bad example and is likely to confuse a new person. The answers spend a lot of time saying not to put visual stuff into the VM, then in this answer he goes and does it.... This sort of approach is both against the principles of MVVM and it invariably leads to masses of smelly code. – slugster Apr 29 '16 at 12:09
  • @slugster. I'd disagree, there's a good debate about it here: http://programmers.stackexchange.com/questions/114090/are-value-converters-more-trouble-than-theyre-worth. In general, I think most people would do it the way I've outlined. There's more than one way of implementing MVVM, as I tried to get across in my answer. Doing it differently =/= doing it wrong. – Joe Apr 29 '16 at 12:09
  • Keeping all visual elements out of the ViewModel might be nice, but in practice it's going to result in ValueConverter galore, and in my opinion would be harder to produce, maintain, and crucially test. – Joe Apr 29 '16 at 12:12
  • That thread is about value converters which is something else again, and they definitely belong to and are associated with the view. There are several key points I would disagree with in the marked answer (IMVHO Rachel's is actually the best). A VM should not be WPF specific - you should be able to use the same one across WPF or Silverlight and with some modifications Winforms. You don't have 'Label' properties to hold text in your VM - bind to a string in a resource file instead. Etc. – slugster Apr 29 '16 at 12:15
  • As for "value converters galore" - yes you are right, but a proliferation of them is usually an indicator of sloppy coding and lack of WPF experience. For example I've seen many cases where converters were used instead of DataTriggers, template selectors, and so on. Converters are a hammer, and to inexperienced coders everything becomes a nail when they have that particular hammer. – slugster Apr 29 '16 at 12:16
  • Good job - I've reversed my downvote :) – slugster Apr 30 '16 at 07:01
  • Yeah, after reading about it I think you're right. – Joe Apr 30 '16 at 19:37
0

1- In many examples I've seen, they recreate the same fields again in VM. What is the purpose, is it enough to have the whole object (City in my example). How about if there are many fields!.

Since the view model is the responsible of implementing view's logic and it performs actions against the model, there're some cases where some properties wouldn't be necessarily part of the model, but they're just there to serve view's requirements.

For example, let's say your model has a Name and Surname, and you want to show a concatenation of both properties in your view. You may be able to implement this using binding expressions or implementing a property in your view model:

public string FullName => $"{Model.Name} {Model.Surname}"; 

2- To be able, to use it in my View (CRUD), how is the CityVm() will be in my example?.

This question has no specific answer. But you'll need a Model property at least to store a given City.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206