5

My application has user controls within user controls. Please see a screen shot of one of the most beautiful applications of all time (UC = user control):

enter image description here

All the properties live in the MainWindow code behind, there are none in my UserControls. To bind to my properties I use

DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1,AncestorType=Window}}"

This works fine but, it does mean all binding properties are in my MainWindow code behind (or the MainWindow ViewModel).

Is this desired in a MVVM (or should I say WPF) approach, in that all the children share the same ViewModel?

6

I think its bad practice to have a God ViewModel, the topmost ViewModel, let's call it MainWindowViewModel, should only hold data and behavior coupled to that of the MainWindow, which usually is very thin, all other work should be delegated to submodels.

If you have a docking manager or other window manager logic that code should reside in the MainWindowViewModel.

Here is a example of a ViewModel I've made that delegates the behavior to sub models

https://github.com/AndersMalmgren/FreePIE/blob/master/FreePIE.GUI/Shells/MainShellViewModel.cs

I do not think it's good practice to pass around data to sub models, it creates dependencies between models. It's better to use a Event aggregation pattern, this way all models interested in data change can subscribe to the event.

Update: I did an improvement to my Main window model, instead of the constructor taking all sub view models it now takes a collection of viewmodels. And then I configure the IoC to inject correct models

private void ConfigurePanels()
{
    kernel.Bind<PanelViewModel>().To<ConsoleViewModel>();
    kernel.Bind<PanelViewModel>().To<ErrorsViewModel>();
    kernel.Bind<PanelViewModel>().To<WatchesViewModel>();
}

This makes the main model a little less coupled to the sub models, before change

    public MainShellViewModel(ConsoleViewModel consoleViewModel,
                              ErrorsViewModel errorsViewModel,
                              WatchesViewModel watchesViewModel
        )
        : base(resultFactory)
    {            
        Tools = new BindableCollection<PanelViewModel> {consoleViewModel, errorsViewModel, watchesViewModel};
    }

and after

    public MainShellViewModel(IEnumerable<PanelViewModel> panels)
        : base(resultFactory)
    {
        Tools = new BindableCollection<PanelViewModel> (panels);
    }

https://github.com/AndersMalmgren/FreePIE/commit/1102292d35a26d7693593266042cde9d9f3b4c89

  • Interesting and big thank you for the link. But if my MainWindow has many UserControls, which are supposed to bind via DependancyProperties, then doens't this mean my MainWindowViewModel has to be a god view? – Dave Jan 14 '14 at 12:12
  • Yeah well, yes and no, it needs to hold the structure of the entire Main window inclding children. But in reality with Dependency injection it only means it needs to hold its closest children. The children will load its own children using IoC. – Anders Jan 14 '14 at 14:00
  • By the way if you have many children directly under Main view then maybe you should start to think about separation of concerns – Anders Jan 14 '14 at 14:03
  • Got an up-vote so took the opportunity to improve my code – Anders May 3 '15 at 10:31
1

Unless overwritten, child controls will inherit the DataContext (except for children of an ItemsControl).

If you aren't explicitly setting the DataContext on all your controls you should be fine (but your coupling is high... ie, your usercontrol now assumes it will only be used in one specific configuration)

If you are explicitly setting the DataContext, then this becomes a problem of Dependency Injection. If a grand-grand-grandchild usercontrols requires data from the topmost viewmodel, then that data should probably be passed to the closest level viewmodel. Think about it. This data is a clearly a dependency of the ViewModel bound to the UserControl.

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.