Navigate through UserControl with MVVM LIGHT (WPF)

雨燕双飞 提交于 2019-12-22 14:18:27

问题


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

回答1:


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.



来源:https://stackoverflow.com/questions/35221894/navigate-through-usercontrol-with-mvvm-light-wpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!