sth_Weird
sth_Weird

Reputation: 660

Communication between parent and child viewmodel via notifychanged or command property?

In my WPF application I'm following the MMV pattern. I have a main View with nested child Views. I have a main VM that holds instances of the child VMs. At some point, the main VM needs to be informed when certain properties of the child VM change.

I have searched the Web a lot. The prefered approach seems to be to use an existing framework (MVVMlight/Prism) and/or some sort of messenger service. Whenever a question dealing with VM-interaction is asked on any board/faq, you can be sure at least one answer suggests using this approach. While I can very well see the advantages of it in a big application (or if you are looking for a "universal" solution), it sometimes seems to be a lot of overhead for small applications.

To me, the most obvious approaches, especially in small applications, would be to

OR

I am wondering if there is something "wrong" with those two approaches in general, for I cannot see them violating MVVM rules? Maybe I am missing something?

Is it ok to use one of these approaches when you can't make use of the advantages of using the messenger based approach in an application?

Upvotes: 7

Views: 4787

Answers (3)

adminSoftDK
adminSoftDK

Reputation: 2092

We use a simple approach for this. When you create this child viewmodels just pass an Action or Func into the contructor. Then invoke that action anytime you need to update the parent view model.

Example

public class ParentViewModel
{
    public ParentViewModel()
    {
        childViewModel = new ChildViewModel(MyAction);
    }

    private void MyAction()
    {
        //i was called by childview model, now do something
    }

    ChildViewModel childViewModel;
}

public class ChildViewModel
{
    private readonly Action action;

    public ChildViewModel(Action action)
    {
        this.action = action;
    }

    private int myVar;

    public int MyProperty
    {
        get { return myVar; }
        set
        {
            myVar = value;
            if (something)
            {
                //call the parent viewmodel
                action.Invoke();
            }
        }
    }
}

Upvotes: 5

Phillip Ngan
Phillip Ngan

Reputation: 16086

Looking at the options of communicating changes made in child viewmodels to their parent viewmodel. For a small application, you are quite right that you don't need to use a messaging bus, event aggregator.

  1. There is nothing wrong with the parent subscribing to the INotifyPropertyChanged events emitted by the child viewmodels. Sure you make the parent depend on the child, but that is OK if you have no need to loosely couple these components.

  2. Passing a command from the parent to the child is not advisable because you're likely to set up a dependency cycle if the parent needs to call commands on the child also.

  3. Another option, if you application is truly small, is to just have one view model. It's fine to have one or more views share a datacontext.

Upvotes: 0

Marek M.
Marek M.

Reputation: 3951

The problem with the first approach is that the main VM has to know about child VMs properties, so you'd be kinda closely tying those two together. While using some kind of a messaging system you'd be able to only pass the data to the 'parent' and no info about internals of its child objects.

The problem with the second approach is testability - if you're writing tests for your vms you'd have to mock those (Relay)Commands in order for you tests to work (or do some null checks inside a method calling it, brrr...) even if it means just passing dumb, empty objects that are doing nothing. Also, usually using messaging component is better because its uniform across all application - you don't have to worry about how to communicate between VMs because you're doing it the same way everywhere :).

As a side note - probably if your app is that small (only master - child vms) you can probably go with any of the approaches you mentioned. I however care for patterns/practices even in small apps because implementing them is simple enough. Effort put in implementing, for example (maybe a custom?) messaging component is not that bigger than the effort you'd have to make to implement anything else :). Hope this is helpful :)

Upvotes: 2

Related Questions