使用MVVM LIGHT(WPF)浏览UserControl

Spe*_*ine 2 c# wpf xaml user-controls mvvm-light

首先,我为我的英语不好而道歉,这不是我的第一语言.

我是MVVM的新手,所以我的问题可能是一个非常新手;)

我在使用WPF和MVVM LIGHT在C#应用程序中切换View时遇到了一些问题.我读了很多文章,但我仍然无法弄清楚如何以干净的方式做到这一点.

所以这是我的问题:在MainWindows中包含的UserControl之间实现导航的最佳方法是什么,假设:

  • 我有一个用于每个UserControl的ViewModel和一个用于主Windows的ViewModel.
  • 用户控件之间切换的按钮包含在UserControl本身中
  • 我有一个ViewModelLocator
  • 我有时需要销毁/重新创建一个userControl的ViewModel
  • 我想尊重MVVM模式.
  • 我想保持简单

Spe*_*ine 5

由于没有人回答我的问题,这就是我最终做的.它可能不是最好的方法,但至少它运作良好.我希望它能帮助像我这样努力学习这种模式的新手:

将CurrentViewModel对象放在MainViewModel中:

public class MainViewModel : ViewModelBase,IMainViewModel
{ 
    /* Other piece of code */

    private ViewModelBase _currentViewModel;

     public ViewModelBase CurrentViewModel
     {
         get
         {
             return _currentViewModel;
         }
         set
         {
             _currentViewModel = value;
             RaisePropertyChanged(() => CurrentViewModel);
         }
     }  
}
Run Code Online (Sandbox Code Playgroud)

显然将它绑定到Mainview(只是相关的代码):

<UserControl Content="{Binding Path=CurrentViewModel}"/>
Run Code Online (Sandbox Code Playgroud)

将DataTemplate放在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>
Run Code Online (Sandbox Code Playgroud)

在ViewModelLocator中使用Simple IOC注册ViewModel:

if (ViewModelBase.IsInDesignModeStatic)
{
    SimpleIoc.Default.Register<IHomeViewModel, DesignHomeViewModel>();
}
else
{
    SimpleIoc.Default.Register<IHomeViewModel, HomeViewModel>();
}
Run Code Online (Sandbox Code Playgroud)

将ViewModelLocator中所有ViewModel的getter设置为Static(只有一个用于示例)

public static IHomeViewModel Home
{
    get{return ServiceLocator.Current.GetInstance<IHomeViewModel>();}
}
Run Code Online (Sandbox Code Playgroud)

由于它是静态的,您可以从MainViewModel访问所需的ViewModel:

public class MainViewModel : ViewModelBase,IMainViewModel
{
        public ViewModelBase HomeVM
        {
            get
            {
                return (ViewModelBase)ViewModelLocator.Home;
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

提供取消注册ViewModel并重新创建它的功能:

public static void CleanUpHome()
{
    SimpleIoc.Default.Unregister<HomeViewModel>();
    SimpleIoc.Default.Register<IHomeViewModel, HomeViewModel>();
}
Run Code Online (Sandbox Code Playgroud)

"子"视图模型通过消息与MainViewModel通信:

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();
        }
}
Run Code Online (Sandbox Code Playgroud)

MainViewModel注册消息并处理它:

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));
    }
Run Code Online (Sandbox Code Playgroud)

就这样.