使用 MVVM LIGHT (WPF) 在用户控件中导航

本文关键字:用户 控件 导航 MVVM LIGHT WPF 使用 | 更新日期: 2023-09-27 18:33:18

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

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

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

所以我的问题来了:在 MainWindows 中包含的用户控件之间实现导航的最佳方法是什么,假设:

  • 我为每个用户控件提供了一个视图模型,对于主窗口有一个视图模型。
  • 用于在用户控件之间切换的按钮包含在用户控件本身中
  • 我有一个视图模型定位器
  • 我有时需要销毁/重新创建用户控件的视图模型
  • 我想尊重 MVVM 模式。
  • 我想保持简单

使用 MVVM LIGHT (WPF) 在用户控件中导航

由于没有人回答我的问题,这就是我最终所做的。这可能不是最好的方法,但至少效果很好。我希望它能帮助一些像我这样正在努力学习这种模式的新手:

将 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);
         }
     }  
}

显然,将其绑定到主视图(仅相关代码(:

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

将 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>

在视图模型定位器中使用简单 IOC 注册视图模型:

if (ViewModelBase.IsInDesignModeStatic)
{
    SimpleIoc.Default.Register<IHomeViewModel, DesignHomeViewModel>();
}
else
{
    SimpleIoc.Default.Register<IHomeViewModel, HomeViewModel>();
}
将视图模型

定位器中所有视图模型的获取器设置为静态(示例只有一个(

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

由于它是静态的,您可以从 MainViewModel 访问所需的视图模型:

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

提供注销视图模型并重新创建它的功能:

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

"子"视图模型通过消息与 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();
        }
}

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));
    }

就这样。