Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM ViewModel and child Views

I'm building an MVVM WPF application, in which there's a wizard with multiple Child Views loaded in a parent View (V) that uses ViewModel (VM) as its data context. One of the MVVM pattern principles states that the VM should not have any knowledge of the V that is bound to it. In this case, VM indeed is not aware of the V, however, the VM (1) manages a list property consisting of different child Views (i.e. different steps), and (2) has another property named CurrentView to dynamically be assigned with an element in the list. CurrentView is bound to a ContentControl in V.

My questions are:

  1. Is is okay to manage (child) Views inside the VM? In other words, the VM does not know about the parent V, but knows which child Views are to be loaded.
  2. Instead of use different child VM for different child Views, I just bind a single parent VM to the parent V, and when a child V is loaded, it can share the same data context with the containing parent V. Is this the right way to do?
like image 308
tab87vn Avatar asked Jan 07 '23 07:01

tab87vn


1 Answers

The parent view model should have knowledge of the child view models, not the child views. Likewise, the parent view, not the view model, should be responsible for switching out the child views.

Here's how you might go about this...

In your view, create some data templates, like this:

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:WizardScreen1ViewModel}">
        <v:WizardScreen1 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:WizardScreen2ViewModel}">
        <v:WizardScreen2 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:WizardScreen3ViewModel}">
        <v:WizardScreen3 />
    </DataTemplate>
</Window.Resources>

Then, in the part of your view where you display the current wizard screen, put a ContentControl, like this:

<ContentControl Content="{Binding CurrentWizardScreenViewModel}" />

In your parent view model, you will need a CurrentWizardScreenViewModel property that fires a PropertyChanged event when it changes.

Then, you need your wizard's next/previous buttons to bind to commands in your parent view model that cause CurrentWizardScreenViewModel to be set to the next/previous screen's view model.

If you do this, the view will automatically take care of switching out the wizard screen view thanks to the magic of data binding.

like image 57
devuxer Avatar answered Jan 10 '23 12:01

devuxer