我正在尝试使用WPF中的MVVM Light Toolkit学习MVVM。但我陷入了一个简单的问题。
我有一个AddEditProfileWindow,它基本上有一个用于配置文件名称的文本框和一个确认按钮。它将新的配置文件添加到数据库表或更新现有配置文件的名称。
在MainWindow/MainViewModel中,我有一个配置文件列表和两个按钮:"添加配置文件"one_answers"编辑所选配置文件"。他们都通过命令+消息打开这个窗口。例如,这里是"添加配置文件"按钮的命令
public RelayCommand OpenAddProfileWindowCommand
{
get
{
return _openAddProfileWindowCommand ?? (_openAddProfileWindowCommand = new RelayCommand(
() => { Messenger.Default.Send(new NotificationMessage("OpenAddProfile")); }));
}
}
它是后面主窗口代码中的接收器
private void MessageReceived(NotificationMessage msg)
{
if (msg.Notification == "OpenAddProfile")
{
var window = new AddEditProfileWindow();
window.Owner = this;
window.ShowDialog();
}
}
所以问题是,我需要以某种方式将一个参数传递给AddEdit。。。Window/ViewModel(例如,在ViewModel中设置IsEditing布尔属性)以更改窗口行为并对其进行一些自定义(将标题和确认按钮文本更改为"添加"或"更新")。同样为了更新,我需要所选记录的Profile对象(或至少Id)。
为了创建ViewModels,我使用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())。
有什么更好/更容易/更清洁的方法吗?
在我看来,Messenger和从IoC获取AddEditProfileViewModel在这种情况下是不合适的。首先,您将消息从UI的DataContext发送到UI。Messenger在松散耦合的组件之间工作,通常在同一级别上,例如视图模型和视图模型。如果希望视图模型通知视图,可以使用Prism中的InteractionRequest。其次,AddEditProfileViewModel可以被认为是一个临时的,基于它的视图是一个模态对话框,所以它的创建可能取决于创建它的环境
一种方法是使用共享服务,可能称为IDialogService,它有一个方法可能称为ShowAddEditDialog。您的主视图模型从IoC获取此服务,并在执行命令add/edit时调用它。调用该方法时,主视图模型还会创建AddEditProfileViewModel和传递状态,如添加/编辑、现有配置文件等。
另一种方法,使用应用程序控制器,如果你仍然想保留Messenger和IoC。您仍然可以在此处使用Messenger,但它不是侦听消息的视图,而是应用程序控制器。现在,应用程序控制器、主视图模型、AddEditProfileViewModel和AddEdit窗口都是从IoC容器中解析的。应用程序控制器同时保存视图模型和侦听消息。当它从主视图模型获得消息时,它更新AddEditProfileViewModel上的状态,解析对话框,设置DataContext并显示对话框。您可以将应用程序控制器实例放在MainWindow代码后面或任何地方,因为一旦从IoC解析,它就是自治的。