Is a ‘God’ ViewModel desired in WPF

mvvmwpf

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?

Best Answer

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

Related Topic