谁应该在MvvmCross中创建视图模型实例

时间:2013-11-13 12:24:28

标签: mvvm viewmodel mvvmcross

只是为了说清楚:我知道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调用放在演示者的逻辑中?我知道这么小的代码并没有太大的区别,但是将它放在演示者的课堂上并减少代码隐藏这不是一个优势吗?

2 个答案:

答案 0 :(得分:2)

ViewModel肯定不应处理与视图(屏幕)有关的任何内容。

我有一个简单的想法是使用自定义演示者,它能够基于ShowViewModel&lt;&gt;创建视图。请求。

自定义演示者是一个视图职责,因此您可以测试屏幕方向。

http://slodge.blogspot.co.uk/2013/06/presenter-roundup.html

答案 1 :(得分:2)

对于这个问题的第二部分:

  

但是如果视图模型的生命周期由演示者控制,我们是否应该尝试将KillMe调用放在演示者的逻辑中?我知道这么小的代码并没有太大的区别,但是将它放在演示者的课堂上并减少代码隐藏这不是一个优势吗?

当前视图模型演示由演示者编排 - 它获取ViewModelRequest个对象并决定如何处理它们。

但是,它通常不会创建ViewModels - 而是:

  • 演示者通常会创建/显示视图
  • 然后,View会在OnCreateViewDidLoadOnNavigatedTo处理过程中创建(或定位)ViewModel。

所以我认为ViewModel的生命周期通常不是“由演示者控制” - 而是我认为ViewModel是“视图模型” - 所以它的生命周期是“由它的视图控制”。

对于ViewModel中需要shutdown / dispose / killMe逻辑的场合,如果你想将该逻辑移回到演示者内部 - 或者转移到其他对象中 - 那么你肯定可以这样做 - 如果你想 - 这是你的应用程序和应用程序是王。

然而,在这些情况下,我怀疑你需要演示者从视图中获得某种通知 - 因为演示者通常不知道何时删除视图(当模式被解除时,按下后退按钮时) ,当Android清除堆栈视图以节省内存等时。)

作为另一种思考方式,如果将演示者重命名为INavigationService,那么您希望INavigationService在您的应用中拥有哪些角色?