How do i design a composite view and view model us

2019-05-24 06:51发布

问题:

I want to create a "Wizard" in my Silverlight MVVM application. The Wizard should contain multiple steps between which you can navigate using "next" and "previous". The problem I am facing is the relationship between views and view models. I want there to be a view and view model for the Wizard itself. My instinct tells me that there should be one view/view model pair for each step in the wizard.

What is a good approach for maintaining these kinds of relationships, where one view model holds several other view models and the view actually consists of several smaller views? Are there any patterns or practices that I can use?

I know this question might be subjective, but give me the rough cuts of an approach and I'll award you an answer!

回答1:

I'd propose main wizard viewModel which has a collection of steps view models and handles navigation between them. While navigating it should call validation methods in step viewModels:

WizardVM:

public class WizardVM
{
     // this commands should support CanExecute
     public ICommand GotoNextCommand { get; private set; } // should open next step VM
     public ICommand GotoBackCommand { get; private set; } // should open previous step VM

     // this prop should be set by 'GotoNext', 'GotoBack' commands
     public object CurrentStep { get; private set; }

     // probably internally you will have a list of all steps:
     private ICollection<object> _stepViewModels = ...;
}

WizardView:

<StackPanel>
    <ContentPresenter Content="{Binding CurrentStep}">
    <StackPanel Orientation="Horizontal">
        <Button Command="{Binding GotoBackCommand}">Back</Button>
        <Button Command="{Binding GotoNextCommand}">Next</Button>
    </StackPanel>
</StackPanel>

UPDATE:

Views can be coupled with ViewModels via Datatemplating. For example add this into resources in App.Xaml:

<DataTemplate DataType="{x:Type local:Step1ViewModel}">
     <Step1View />
</DateTemplate>
<DataTemplate DataType="{x:Type local:Step2ViewModel}">
     <Step2View />
</DateTemplate>

Your viewModels should know absolutely nothing about views. It means that WizardVM should expose only other viewModels but not views. It's a rule of thumb for MVVM.

UPDATE2 Oops, I forgot that Silverlight doesn't have DataTemplating yet. In silverlight I would still expose ViewModels but bind them to ContentPresenters using a converter which will convert a viewModel into corresponding view.