想象一下,我有一个显示客户通用列表的视图。在这种情况下,我将实现CustomersViewModel
绑定到XAML Button的RelayCommand
,下载它并填充ObservableCollection
Customer
,绑定到{{1} }}
如果我想定义一个ListView
,一个显示有关客户的其他信息的视图,我会创建一个CustomerDetailView
,一个CustomerDetailViewModel
,并重复相同的逻辑。但不同之处在于ViewModel必须将选定的Customer作为参数,而CustomerView
每次都可以显示,而无需外部参数。
在WinForm解决方案中,我会放置一个参数来构造我需要的对象形式。
我的问题是:为了尊重MVVM模式,实施此类导航的正确方法是什么?
我的导航逻辑:
CustomersViewModel
我认为的选项:
以某种方式将参数传递给" NavigateTo"函数,并在构造函数中定义具有此参数的相对ViewModel。我没有办法做到这一点,虽然这对我来说似乎是合理的。
如上导航,然后向ViewModel发送消息。这个想法很有效,但我并不相信。在我看来,似乎有一种方法可以使一件简单的事情复杂化。
static ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
var nav = new NavigationService();
nav.Configure("CustomersView", typeof(CustomersView));
nav.Configure("CustomerDetailView", typeof(CustomerDetailView));
SimpleIoc.Default.Register<INavigationService>(() => nav);
SimpleIoc.Default.Register<CustomersViewModel>();
SimpleIoc.Default.Register<CustomerDetailViewModel>();
}
private RelayCommand _navigateToCustomerDetailCommand;
public RelayCommand NavigateToCustomerDetailCommand
{
get
{
return _navigateToCustomerDetailCommand
?? (_navigateToCustomerDetailCommand = new RelayCommand(
() =>
{
_navigationService.NavigateTo("CustomerDetail");
}
{
}
在ViewModel中收听该消息:
return _navigateToCustomerDetailCommand
?? (_navigateToCustomerDetailCommand = new RelayCommand(
() =>
{
_navigationService.NavigateTo("CustomerDetail");
Messenger.Default.Send(new CustomMessageCustomerSelected(SelectedCustomer));
}
答案 0 :(得分:1)
这两种选择都是适当的方法。您应该使用哪一个取决于应用程序的UI和工作流程。具体来说,您如何访问详细信息视图?比如,如果你点击一个按钮打开一个新的屏幕&#34; (启动一个全新的视图来替换用户正在查看的内容),然后你应该使用选项1.如果你有一个类似客户列表的东西与详细信息视图并排,并且视图应该在新客户时更新单击,然后使用选项2.
要实现第一个选项,您需要使用控件容器和ViewModelLocator类的SimpleIoc反转。您使用定位器注册ViewModel,然后使用该定位器处理对新VM的请求并调用其构造函数。这意味着您可以轻松地将包含客户的消息作为参数发送,然后将其提供给VM的构造函数。 Here is a decent introduction to ViewModelLocator,虽然已有几年了,但here is a quick and dirty intro to SimpleIoc。
顺便说一句,如果您要拥有多个并发用户(特别是选项2),我建议发送客户的ID,而不是对象。这意味着您必须从存储中获取它,这是一个小的性能影响,但也意味着您的用户在打开视图时始终获取最新数据,这反过来减少了编辑冲突。