Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 来自ViewModels的MVVM导航_C#_Wpf_Mvvm - Fatal编程技术网

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
    hosts
    UserControl
    ?这不是MvvM
    UserControl
    不能靠近
    ViewModel
    。但是,如果UserControl使用LoginViewModel,因为它是不同的数据上下文。您可以使用LoginViewModel上的事件来确定用户何时登录,并在MainViewModel中处理该事件。@XAMlMAX为不清楚表示歉意。您的第二条语句是正确的,
    LoginView
    承载一个
    UserControl
    ,它使用
    LoginView模型作为其数据上下文。啊,好的。您仍然可以在
    MainWindowViewModel
    public class NavigateToViewNotification
    {
        public string ToView { get; set; }
    }
    
    public LoginViewModel(MainWindowViewModel vm)
    {
        _vm = vm;
    }