Question

Given the following scenario:

  1. ViewModelA launches ViewModelB (via a common Controller, of course, that uses Ioc and DI to resolve the types needed).
  2. ViewModelB needs to set a property value in ViewModelA.

Is it bad to simply inject ViewModelA into ViewModelB via constructor injection and just set the property directly?

Or…

Should a messaging system like the EventAggregator from Prism be used to handle all communication between ViewModels?

I like the injection approach because it’s easy, but my instincts are telling me I’m missing something. I call on your collective wisdom to help fill in my blind spot.

Was it helpful?

Solution

I suggest you read this question (and my answer) since it's similar, but not exactly your problem. It does deal with communication of properties between parent/child ViewModel objects.

Let's look at a basic example:

  • ViewModelA is the parent and has to present the Sum of some property on B
  • ViewModelB is the child and has a property that needs summing

So the user makes a request to edit the property on B and the request succeeds, so B presumably changes the value of its property and fires a PropertyChanged event.

ViewModelA could subscribe to the events on all children, but having gone down that path, I don't like it. When children are added and removed, you have a lot of bookkeeping to do.

Injecting A into B is cleaner, but you still have a lot of bookkeeping to do. What if you have a "Clear Children" action on A? You have to remember to properly get rid of the parent relationship from B to A in all cases. Still it's better than events in my opinion because it's more explicit.

Personally I like the messaging idea. I'm more familiar with MVVM Light's messenger than Prism, but it's the same idea... a global message bus. At any time, any B can say "I changed my property!" and then A listens for the notification and does the computation itself. I think this is your cleanest solution with much less bookkeeping.

OTHER TIPS

I consider it a code smell if you need two-way references. Often you can replace one of the references with an event.

Let ViewModelB raise an event that ViewModelA subscribes to. A complete messaging system like the one found in Prism is certainly an option, but in your scenario it sounds like a 'normal' event will do just fine.

I suggest using a much lighter dedicated Messaging solution called "Light Message Bus". It is not part of any yet another ;-) MVVM framework, but independent component. And I got it working in no time in less than 3 minutes.

You might find the sample applications of the WPF Application Framework (WAF) useful. The ViewModels don't know about each other. The mediation between them is done by Controllers. This way you can prevent cyclic dependencies between ViewModel objects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top