ViewModels的MVVM导航

时间:2017-07-13 14:14:06

标签: c# wpf mvvm

我有一个MainWindow,它有自己的ViewModel,我想用它来进行导航。它看起来像这样:

public MainWindowViewModel()
{
    SelectedViewModel = new LoginViewModel();

    DashboardCommand = new DelegateCommand(OpenDashboard);
}

private object _selectedViewModel;

public object SelectedViewModel
{
    get => _selectedViewModel;
    set
    {
        _selectedViewModel = value;
        OnPropertyChanged("SelectedViewModel");
    }
}


public ICommand DashboardCommand { get; set; }

private void OpenDashboard(object obj)
{
    SelectedViewModel = new DashboardViewModel();
}

我有一个LoginView,其中包含UserControl个简单表单,用户可以输入详细信息,然后点击Button进行登录。当用户点击Button时,会执行检查,如果通过,我想从DashboardView导航到LoginViewModel。这是LoginViewModel

的摘录
#region Login
private DelegateCommand _loginCommand;
public ICommand RegisterCommand
{
    get
    {
        _loginCommand = new DelegateCommand(param => Login());
        return _loginCommand;
    }
}

private void Login()
{
    if (LoginCheck())
    {
        // TODO: Navigate to the DashboardView
    }
}
#endregion

我的问题是如何从MainWindowViewModel

导航LoginViewModel

2 个答案:

答案 0 :(得分:1)

您的案例是何时在MVVM中使用消息传递的一个很好的例子。

执行检查并通过后,您应该从LoginViewModel发送消息。 MainWindowViewModel应该注册此消息并进行导航。

要使用消息传递,您可以使用发布/订阅模式。要做到这一点,你不必实现它。您可以使用几个实现的MVVM库。

例如,您可以使用MVVM Light:

ViewModelBase继承您的ViewModel,然后您可以使用MessengerInstance发送和注册消息。

传递检查时您在LoginViewModel中的代码:

MessengerInstance.Send(new NavigateToViewNotification(){ToView="Dashboard"});

您在MainWindowViewModel中的代码(在consturctor中):

MessengerInstance.Register<NavigateToViewNotification>(this, ntv=> {/* here imlement the navigation ntv.ToView has the info to which view*/});

NavigateToViewNotification是你自己的班级:

public class NavigateToViewNotification
{
    public string ToView { get; set; }
}

这样就可以避免在ViewModel之间直接引用,从而导致松散耦合的ViewModel,从而更容易维护客户端代码。

答案 1 :(得分:1)

  

我的问题是如何从LoginViewModel导航MainWindowViewModel?

三个选项。

  1. 保留对MainWindowViewModel LoginViewModel的强烈引用,例如在创建前者时将前者注入后者的实例:

    public LoginViewModel(MainWindowViewModel vm)
    {
        _vm = vm;
    }
    
  2. 这会在两种类型之间创建一个强耦合,或者更确切地说是应该能够导航的任何子视图模型类型和MainWindowViewModel

    1. 使用信使或事件聚合器,并将导航邮件从LoginViewModel发送到MainWindowViewModelhttps://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/
    2. 这消除了视图模型类型之间的强耦合,但使代码更复杂,因为不再直接引用导航发生的MainWindowViewModel

      LoginViewModel只是使用事件聚合器引发事件,然后它并不真正关心谁(如果有的话)实际处理该消息并执行实际导航。

      1. 使用您注入两个视图模型的共享导航服务。然后,他们浏览此服务,而不是浏览MainWindowViewModel
      2. 这使得所有视图模型彼此松散耦合。他们只了解并依赖共享服务。