MVVM Light:如何向ViewModel发送参数(打开新窗口时)?

时间:2013-07-26 15:38:43

标签: wpf mvvm mvvm-light

我正在尝试使用WPF中的MVVM Light Toolkit学习MVVM。但我坚持一个简单的问题。

我有一个AddEditProfileWindow,它基本上有一个配置文件名称的文本框和一个确认按钮。它将新配置文件添加到数据库表或更新现有配置文件的名称。

在MainWindow / MainViewModel中,我有一个配置文件列表和两个按钮:“添加配置文件”和“编辑所选配置文件”。他们都通过命令+消息打开这个窗口。例如,这里是“添加配置文件”按钮的命令

    public RelayCommand OpenAddProfileWindowCommand
    {
        get
        {
            return _openAddProfileWindowCommand ?? (_openAddProfileWindowCommand = new RelayCommand(
                () => { Messenger.Default.Send(new NotificationMessage("OpenAddProfile")); }));
        }
    }

它是MainWindow代码中的接收器

private void MessageReceived(NotificationMessage msg)
{
    if (msg.Notification == "OpenAddProfile")
    {
        var window = new AddEditProfileWindow();
        window.Owner = this;
        window.ShowDialog();
    }
}

所以问题是我需要以某种方式将参数传递给AddEdit ... Window / ViewModel(例如在ViewModel中设置IsEditing bool属性)来改变窗口行为并稍微自定义(更改标题和确认按钮)文本“添加”或“更新”)。另外,对于更新,我需要所选记录的Profile对象(或至少Id)。

为了创建ViewModel,我使用ViewModelLocator和Unity

    public ViewModelLocator()
    {
        var container = new UnityContainer();

        ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(container));

        container.RegisterType<MainViewModel>(new ContainerControlledLifetimeManager()); // singleton
        container.RegisterType<AddEditProfileViewModel>(); 
    } 

    public AddEditProfileViewModel AddEditProfile
    {
        get
        { return ServiceLocator.Current.GetInstance<AddEditProfileViewModel>();  }
    }

我已经阅读了很多类似的线程和示例,但仍然不明白我应该如何传递参数来查看模型。一些答案建议在应用程序启动时创建视图模型(并使它们成为单例)在ViewModelLocator中,然后我可以在打开之前发送消息。但看起来不是很干净,我还需要在打开之前重置视图模型(可能通过Cleanup())。

有没有更好/更容易/更清洁的方法?

1 个答案:

答案 0 :(得分:1)

在我看来,Messenger和从IoC获取AddEditProfileViewModel并不适合这种情况。首先,您将消息从UI的DataContext发送到UI。 Messenger在松散耦合的组件之间工作,通常在同一级别上,例如视图模型和视图模型。如果希望视图模型通知视图,可以使用Prism中的InteractionRequest。其次,AddEditProfileViewModel可以被视为临时的,基于其视图是模态对话框,因此其创建可能取决于创建它的环境。

使用共享服务的一种方法可能称为IDialogService,其方法可能称为ShowAddEditDialog。您的主视图模型从IoC获取此服务,并在执行命令,添加/编辑时调用它。调用方法时,主视图模型还会创建AddEditProfileViewModel并传递状态,例如添加/编辑,现有配置文件等。

另一种使用应用程序控制器的方法,如果您仍想保留Messenger和IoC。你仍然可以在这里使用Messenger,但它不是监听消息的视图,而是一个应用程序控制器。现在,应用程序控制器,主视图模型,AddEditProfileViewModel和AddEdit窗口都是从IoC容器中解析出来的。应用程序控制器保存两个视图模型并监听消息。当它从主视图模型获得消息时,它会更新AddEditProfileViewModel上的状态,解析对话框,设置DataContext并显示对话框。您可以将应用程序控制器实例放在MainWindow代码后面或任何地方,因为一旦从IoC解析它,它就是自治的。