1

I have a MainWindow which consists of several UserControls.

Currently, I have one God ViewModel.cs which is defined at MainWindow level and does the job for all the UserControls.

Now I feel that this is not the right way to do it. Maybe I should have separate viewmodels for each of the user controls, right? But my problem is how to interact between these? Let's say some event happens in usercontrol1 which changes something in usercontrol2's viewmodel?

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
Vahid
  • 5,144
  • 13
  • 70
  • 146
  • 3
    Does a TextBox have a VM? Does a ListView have a VM? Does a Grid have a VM? *Then why should a UserControl have a VM?* This is a code smell. It smells like the failure you will encounter when you try to do this. Just create public properties on your UserControl, bind those to your VMs, then inside your UCs xaml bind to those properties. Or do whatever UI logic you need to do in the codebehind. –  Dec 02 '14 at 18:44
  • @Will Thanks Will, you mean I should bind the public property in two-way mode to the VM? – Vahid Dec 02 '14 at 19:09
  • public DependencyProperties on the surface of your UserControls. Bind to them from within, bind to them from without. Bind them every which way you can. Go forth! And bind! –  Dec 02 '14 at 19:15
  • @Will Can you show this to me with a very simple example in an answer? I like your sense of humor by the way ;) – Vahid Dec 02 '14 at 19:19
  • This answer has an example http://stackoverflow.com/q/22912039/managing-and-binding-usercontrols/22914210#22914210 a longer explanation of the code smell http://stackoverflow.com/questions/25795871/wpf-databinding-with-mvvm-and-user-controls/25796096#25796096 and another http://stackoverflow.com/questions/21093396/to-use-datacontext-or-not-to-use/21096903#21096903 hope that helps. –  Dec 02 '14 at 20:07

2 Answers2

3

You should use events to control interactions between the viewmodels. The problem with using regular .NET events is that it couples the viewmodels, since they would have explicit knowledge of eachother.

To get around this you could use an existing MVVM framework that provides an 'event broker', that is, a mechanism through which viewmodels can subscribe to, and publish events without having to know about eachother.

Examples of MVVM frameworks are PRISM, Caliburn Micro, MVVM Light etc.

You could also roll your own event broker but probably better to go with an existing one unless you have a good reason not to.

user469104
  • 1,206
  • 12
  • 15
3

There is no definitive answer for this, it depends on the situation. However, some advice for different situations:

  1. If the user controls are just fancy displays for simple data, they probably don't need a view model. The required properties can be exposed via dependency properties and bound to the master view model.

  2. If the user controls are large (and you are using them more like pages) then they would be mostly independent, so interaction is not a concern. If they need to modify some global state, then they could do so in order to update other view models

  3. If there is a lot of interaction, then you likely haven't correctly encapsulated your user controls. In general, I would try to fix that, and if I can't, put shared data in the master view model, and pass that object to the child view models so they can access it.

You also need to be careful with user control view models, if you set the control's DataContext property, your bindings on the user control from the master control will not work as you expect. A simple work around is to use the root UIElement's DataContext for the child view model.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Thanks Bradley, actually I have currently set the DataContext of the mainwindow to all its child usercontrols and it is working fine. One of the usercontrols is so big but not independent I guess I will have to stick to this architecture till I expand my knowledge regarding MVVM. – Vahid Dec 02 '14 at 19:12