1

I am learning the MVVM paradigm and I have seen a few different implementations surrounding the Model and how it is updated which I want to understand.

My understanding of the View and ViewModel interaction is clear (I think) and is as follows:

  • Properties in a View are bound to properties in a ViewModel
  • ViewModels do not know about a View but a View does know about a ViewModel
  • Changes in a View set property values in the ViewModel through bindings
  • Changes to a ViewModel property are received by Views as they are bound to properties in the ViewModel*

Typically I have seen INotifyPropertyChanged being implemented in the ViewModel to notify Views of changes.

The question I have is how changes are propagated to the model.

Example

Let's say that I am making an application to control an audio player ("AudioApp") and I am focusing just on AudioApp's volume for simplicity.

I would have (psuedocode):

// ApplicationModel.cs
public class Application
{
    private float volume;
    public float Volume;
}

And

// ApplicationViewModel.cs
public class Application
{
    private float volume;
    public float Volume
    {
        get => volume;

        set
        {
            // Let's pretend the slider goes 0 -> 1 and this needs 0 -> 100
            if (volume == value * 100) return;

            volume = value * 100;
            RaisePropertyChanged("Volume");
        }
    }

And

// VolumeView.cs
<Rectangle Fill="Blue" Height="{Path = Volume, Mode = TwoWay}"/>

Question Part 1. If a View sets a property directly on the ViewModel, and the ViewModel updates a View via bound properties and INotifyPropertyChanged how do property changes ever reach the Model?

This tutorial actually implements INotifyPropertyChanged in the Model and uses an ObservableCollection in the ViewModel, but I thought the idea was to set property values in the ViewModel, not in the Model directly. Additionally, this doesn't work for my example, where there are not collections of instances of the model.

Similarly, this answer recommends the following flow:

 1. Viewmodel is created and wraps model
 2. Viewmodel subscribes to model's `PropertyChanged` event
 3. Viewmodel is set as view's `DataContext`, properties are bound etc
 4. View triggers action on viewmodel
 5. Viewmodel calls method on model
 6. Model updates itself
 7. Viewmodel handles model's `PropertyChanged` and raises its own `PropertyChanged` in response
 8. View reflects the changes in its bindings, closing the feedback loop

but other answers say:

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.

Question Part 2. That quote does not make sense to me. Even if only one object is making changes to the Model's data, how does the object change the data (and how does that object receive its update?

Question Part 3. (Most important) the reason this matters is because my app ultimately needs to update AudioApp's volume through a network request. Am I correct that the network communication would be considered "business logic" and therefore be handled by the model when it's volume property changes (assuming I can figure out the canonical way to do that)?

*Bonus: Does this cause a feedback loop where changing a slider (View) from .5 -> .6 -> .7 would change the value in the ViewModel from .5 -> .6 which would then update the View (which is now at .7) back to .6?

2 Answers 2

2

In the general case MVVM fits neatly the CSQ pattern (Command-query Separation):

  • Queries deliver the data downstream (model → viewmodel → view).
  • Commands are sent upstream (view → viewmodel → model), possibly causing changes in the data.
  • Bindings may be considered syntactic sugar for establishing a reactive command and a reactive query in a single expression.
  • INotifyPropertyChanged is a trigger for a query.

Not every MVVM implementation will be that clean, but thinking about streams of data and events should make the picture easier to understand.

enter image description here

As you can see, in terms of communication components of MVVM are not that different from each other, the differences mostly come from the scope and syntax.


So when should the viewmodel issue a command to the model? When it makes sense to, really. All you need is a trigger, such as an user interaction or a timer. To be more specific, most common cases are:

  • The user clicks a button, causing the view send a command to the viewmodel, then viewmodel's command handler sends another comand to the model.
  • The viewmodel detects a change, caused by a binding, and decides to send a command to the model. Remember, viewmodels's property setter may be considered a special case of a command.
  • Viewmodel sends commands on its own, without the view's interaction. For example, running a background task to save the draft periodically, as I am typing right now.

Once the command is issued, the best practice is to just wait for update patiently — that is, to do nothing. If the model decides that the changes it made (if any) must be relevant to the viewmodel, it will publish an update (via INotifyPropertyChanged or IObservable) which make viewmodel to trigger it's queries.

If you do not follow the aforementioned practice on relying on a query for updates, you may cause subtle bugs by assuming an invalid state: the model may modify or even reject the state that you've sent with a command, or it may have been changed by other actors in parallel.

(Some MVVM frameworks are very guilty for doing this, making some bindings impossible without manual workarounds. Never assume that upstream has accepted your changes as is or at all.)

Bu the way, the same is applicable for the view—viewmodel relationship.

Also remember that viewmodels can have state that is relevant to the view only. It means that not every command must cause an interaction with the model.

2
  • " If the model decides that the changes it made (if any) must be relevant to the viewmodel, it will publish an update (via INotifyPropertyChanged or IObservable) " so then the model implementing INotifyPropertyChanged to the ViewModel is an acceptable practice?
    – Startec
    Jun 10, 2021 at 4:39
  • 1
    @Startec There are 2 general ways to implement the model. The first way is to encapsulate business logic into an object literally called Model. The second way is to interpret the term Model as a collective name for objects (APIs) of the business layer. In the first case the Model is usually a part of the UI, so using INotifyPropertyChanged is warranted. In the second case, most often there's no objects with properties that can change, rather, there are services that can handle commands and emit events, so INotifyPropertyChanged makes little sense here. Jun 10, 2021 at 10:17
0
  1. It is the viewmodels responsibility to update the model, usually you would have an instance of that model provided to it somehow, possibly through dependency injection. So setting the volume on the view model should then set the volume on the instance of the model that it has been given. It would be the view models responsibility to handle any conversion if necessary.

    There's nothing wrong with binding things in the view directly to a model, the main reason for having a view model is so you can separate the concerns of the view with the model itself, if you see yourself introducing view concerns into your model then that might indicate you need that extra layer of separation.

  2. If only one object is changing the data, then that object is always going to know when that value has changed and what it's being changed to, as it is the one making the change.

    For example, if you have a textbox bound to a property and you typed in the text "XYZ" which the textbox then set "XYZ" on that property, there is no need for the property to say "hey textbox! my value has changed to XYZ".

    I would say that comment is slightly misleading however as this only applies if the same object is the only one reading as well as writing the value.

  3. I would probably consider it business logic.

Generally, updates between the view and the viewmodel are synchronous, so by the time you got it to .7 it would have already been updated on the model.

If you add a delay in, maybe setting the volume also triggers a network request to go out and get you get a response back which causes the value to be updated then you would experience that kind of behaviour. Depending on what you're trying to achieve, you could bind commands on your view model, that pause any external updates until the user has finished playing with the controls or something like that.

1
  • that object is always going to know when that value has changed and what it's being changed to — that's how you'll get the bug mentioned by OP in the last paragraph. May 8, 2021 at 15:56

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.