【问题标题】:Who should create view model instances in MvvmCross谁应该在 MvvmCross 中创建视图模型实例
【发布时间】:2013-11-13 12:24:27
【问题描述】:

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

【问题讨论】:

    标签: mvvm viewmodel mvvmcross


    【解决方案1】:

    ViewModel 绝对不应该处理与视图(屏幕)有关的任何事情。

    我的一个快速想法是使用自定义演示器,它能够根据 ShowViewModel 请求创建视图。

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

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

    【讨论】:

    • 谢谢。我会检查您引用的博客文章中的链接。
    • 我同意这个选项 - 我更喜欢父 VM 调用 ShowViewModel(或其他一些服务),而不是直接在 if 语句中创建 VM。
    【解决方案2】:

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

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

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

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

    • 演示者通常会创建/显示视图
    • 然后视图创建​​(或定位)一个 ViewModel 作为OnCreateViewDidLoadOnNavigatedTo 处理的一部分。

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

    对于在 ViewModel 中需要关闭/处置/killMe 逻辑的情况,如果您想将该逻辑移回演示者内部 - 或移到其他对象中 - 如果您愿意,您绝对可以这样做 - 这是您的应用,应用为王。

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

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

    【讨论】:

    • 谢谢。您为我澄清了视图和演示者之间的职责划分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    • 2021-05-21
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多