明确一点:我知道 MvvmCross 在创建视图模型的位置和方式方面非常灵活。我的问题更多是关于适当分离关注点,以简化复杂跨平台应用程序的设计。
考虑我们有一个包含客户列表和客户详细信息的应用程序。在 iPad 和 Surface 上,列表和详细信息显示在同一页面上,但在较小的设备上,选定客户的客户列表和详细信息在不同的页面之间拆分。所以我们有一个带有 CustomerListViewModel 和 CustomerDetailsViewModel 的 PCL。现在我们应该如何从可移植类库中管理视图模型的生命周期?
我最初是使用 CustomerListViewModel 实现中的代码完成的,如下所示:
public ICommand SelectCustomerCommand
{
get { return new MvxCommand(SelectCustomer); }
}
public void SelectCustomer()
{
if (formFactor == FormFactor.Phone)
{
ShowViewModel<CustomerDetailsViewModel>(new CustomerDetailsViewModel.NavObject(this.SelectedCustomer));
}
else
{
this.CustomerDetails = new CustomerDetailsViewModel(this.SelectedCustomer);
}
}
这里最重要的是我们要么调用 ShowViewModel,它反过来要求演示者构造一个 CustomerDetailsViewModel 对象并将其呈现在新页面中,要么显式创建 CustomerDetailsViewModel 的实例并将其绑定到 CustomerDetails。
在看过 N+1 MvvmCross 视频系列的第 32 和 42 集之后,我不确定这是不是正确的做法。当然可以,但是视图模型是否应该关心其他视图模型的实例化细节?
我的第二个想法是重构此代码并将此逻辑放入演示器中,因此我可以简单地编写 CustomerListViewModel 实现:
public void SelectCustomer()
{
ShowViewModel<CustomerDetailsViewModel>(new CustomerDetailsViewModel.NavObject(this.SelectedCustomer));
}
...演示者将在 ShowViewModel 调用触发的代码中完成其余的工作。然而,在第 42 集中,它展示了如何直接从关联视图控制视图模型生命周期:
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
VisibleViewModel.IsVisible(false);
if (e.NavigationMode == NavigationMode.Back)
KillableViewModel.KillMe();
}
但是如果视图模型的生命周期是由演示者控制的,我们不应该尝试将 KillMe 调用放在演示者的逻辑中吗?我知道这么小的一段代码并没有太大的区别,但是把它放在演示者的课堂上并减少代码隐藏难道不是一个优势吗?