C# 来自ViewModels的MVVM导航
我有一个C# 来自ViewModels的MVVM导航,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个main窗口,它有自己的ViewModel,我想用于导航目的。看起来是这样的: public MainWindowViewModel() { SelectedViewModel = new LoginViewModel(); DashboardCommand = new DelegateCommand(OpenDashboard); } private object _selectedViewModel; public object SelectedViewMode
main窗口
,它有自己的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
,它有一个简单的表单,允许用户输入他们的详细信息,然后单击按钮登录。当用户单击按钮时,将执行检查,如果检查通过,我希望从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
我的问题是如何从LoginViewModel
在MainWindowViewModel
上导航?您的案例就是在MVVM中何时使用消息传递的一个很好的例子
执行并通过检查后,您应该从LoginViewModel发送一条消息。MainWindowViewModel应注册此消息并进行导航
要使用消息传递,可以使用发布/订阅模式。要做到这一点,您不必实现它。您可以使用几个实现is的MVVM库
例如,您可以使用MVVM灯光:
从ViewModelBase
继承您的ViewModel,然后您就有了一个Messenger实例
,可以用来发送和注册消息
通过检查时,您在LoginViewModel中的代码:
MessengerInstance.Send(new NavigateToViewNotification(){ToView="Dashboard"});
您在MainWindowViewModel中的代码(在consturctor中):
这样,您就避免了ViewModels之间的直接引用,这将导致松散耦合的ViewModels,从而更容易维护客户机代码
我的问题是如何从LoginViewModel在MainWindowViewModel上导航
三种选择
从LoginViewModel
中保留对MainWindowViewModel
的强引用,例如,在创建前者时,将后者的实例注入前者:
public LoginViewModel(MainWindowViewModel vm)
{
_vm = vm;
}
这将在这两种类型之间创建一个强耦合,或者更确切地说,在假定能够导航的任何子视图模型类型和MainWindowViewModel
之间创建一个强耦合
使用messenger或事件聚合器,将导航消息从LoginViewModel
发送到MainWindowViewModel
:
这消除了视图模型类型之间的强耦合,但由于不再直接引用发生导航的MainWindowViewModel
,代码变得更复杂
LoginViewModel
只是使用事件聚合器引发一个事件,它并不真正关心谁(如果有的话)实际处理该消息并执行实际的导航
使用向两个视图模型注入的共享导航服务。然后,它们通过该服务导航,而不是通过MainWindowViewModel
导航
这使得所有视图模型彼此松散耦合。他们只知道并依赖共享服务。如何使用DI让viewmodels相互了解,并让viewmodels知道他们的视图(窗口)。LoginViewModel
hostsUserControl
?这不是MvvMUserControl
不能靠近ViewModel
。但是,如果UserControl使用LoginViewModel,因为它是不同的数据上下文。您可以使用LoginViewModel上的事件来确定用户何时登录,并在MainViewModel中处理该事件。@XAMlMAX为不清楚表示歉意。您的第二条语句是正确的,LoginView
承载一个UserControl
,它使用LoginView模型作为其数据上下文。啊,好的。您仍然可以在MainWindowViewModel
public class NavigateToViewNotification
{
public string ToView { get; set; }
}
public LoginViewModel(MainWindowViewModel vm)
{
_vm = vm;
}