Navigate through UserControl with MVVM LIGHT (WPF)

First of all I apologize for my poor english which is not my first language.

I'm new in MVVM so my question is probably a very newbie one ;)

I'm encountering some issue with switching View in a C# Application using WPF and MVVM LIGHT. I've read a lot of articles but i still can't figured out how to do it in a clean way.

So here is my question: What is the best way to achieve the navigation between UserControl contained in a MainWindows, assuming that:

  • I've a ViewModel for each UserControl and one for the Main Windows.
  • The buttons for switching between usercontrols are contained into UserControl itself
  • I've a ViewModelLocator
  • I need to sometimes Destroy/re-create a userControl's ViewModel
  • I want to respect the MVVM Pattern.
  • I want to keep it simple

  • Since nobody answers to my question, this is what I finally did. It might not be the best way but at least it works well. I hope it'll helps some newbies like me who are struggling learning this pattern:

    Put a CurrentViewModel Object in the MainViewModel:

    public class MainViewModel : ViewModelBase,IMainViewModel
    { 
        /* Other piece of code */
    
        private ViewModelBase _currentViewModel;
    
         public ViewModelBase CurrentViewModel
         {
             get
             {
                 return _currentViewModel;
             }
             set
             {
                 _currentViewModel = value;
                 RaisePropertyChanged(() => CurrentViewModel);
             }
         }  
    }
    

    Obviously bind this to the Mainview (Just the relevant code):

    <UserControl Content="{Binding Path=CurrentViewModel}"/>
    

    Put the DataTemplate in the App.xaml:

      <Application.Resources>
            <ResourceDictionary>
                <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
                <DataTemplate DataType="{x:Type localViewModel:HomeViewModel }">
                    <localView:AccueilView/>
                </DataTemplate>
                <DataTemplate DataType="{x:Type localViewModel:ErrorViewModel }">
                    <localView:ErrorView/>
                </DataTemplate>
            </ResourceDictionary>
        </Application.Resources>
    

    Register the ViewModel with Simple IOC in the ViewModelLocator:

    if (ViewModelBase.IsInDesignModeStatic)
    {
        SimpleIoc.Default.Register<IHomeViewModel, DesignHomeViewModel>();
    }
    else
    {
        SimpleIoc.Default.Register<IHomeViewModel, HomeViewModel>();
    }
    

    Set the getter of all the ViewModel in the ViewModelLocator to Static (just one for the exemple)

    public static IHomeViewModel Home
    {
        get{return ServiceLocator.Current.GetInstance<IHomeViewModel>();}
    }
    

    Since it's static you can access the ViewModel you want from the MainViewModel:

    public class MainViewModel : ViewModelBase,IMainViewModel
    {
            public ViewModelBase HomeVM
            {
                get
                {
                    return (ViewModelBase)ViewModelLocator.Home;
                }
            }
    }
    

    Provide the ability to unregister the ViewModel and recreates it:

    public static void CleanUpHome()
    {
        SimpleIoc.Default.Unregister<HomeViewModel>();
        SimpleIoc.Default.Register<IHomeViewModel, HomeViewModel>();
    }
    

    The "child" View Model communicates with the MainViewModel through messages:

    public class ErrorViewModel : ViewModelBase, IErrorViewModel
    {     
        /*Other piece of code */
    
            public void HomeReturn()
            {
                var msg = new ChangeView(ChangeView.EnumView.Home);
                Messenger.Default.Send<ChangeView>(msg);
                ViewModelLocator.CleanUpErrors();
            }
    }
    

    The MainViewModel Register to the message and processes it:

    public class MainViewModel : ViewModelBase,IMainViewModel
    {
        public MainViewModel()
        {
            Messenger.Default.Register<ChangeView>(this, (action) => ReceiveMessage(action));
            CurrentViewModel = HomeVM;
        }
    
        private void ReceiveMessage(ChangeView viewName)
        {
            switch (viewName.switchView)
            {
                case ChangeView.EnumView.Home:
                    CurrentViewModel = HomeVM;
                    break;
                case ChangeView.EnumView.Error:
                    CurrentViewModel = ErrorVM;
                    break;
                }
            Messenger.Default.Unregister<ChangeView>(this, (action) => ReceiveMessage(action));
        }
    

    That's all.

    链接地址: http://www.djcxy.com/p/56186.html

    上一篇: 使用MVVM模式而不使用导航视图的WPF swtich视图

    下一篇: 通过MVVM LIGHT(WPF)导航UserControl