Just to make it clear: I know MvvmCross is very flexible about where and how view models can be created. My question is more about proper separation of concerns, to simplify design of complex cross-platform applications.
Consider we have an app with customer list and customer details. On iPad and Surface the list and details are shown on the same page, but on smaller devices customer list and details for a selected customer are split between separate pages. So we have a PCL with CustomerListViewModel and CustomerDetailsViewModel. Now how should we manage view model lifetime from within the portable class library?
I originally did it using code in CustomerListViewModel implementation that looks like this:
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);
}
}
What is essential here is that we either call ShowViewModel that in turns asks a presenter to construct a CustomerDetailsViewModel object and render it in a new page or explicitly create an instance of CustomerDetailsViewModel and bind it to CustomerDetails.
After having seen episodes 32 and 42 of N+1 MvvmCross video series I am not quire sure this is the right way to do it. Of course it works, but should a view model care about instantiation details of other view model?
My second thought was to refactor this code and put this logic into a presenter, so I can simply write in CustomerListViewModel implementation:
public void SelectCustomer()
{
ShowViewModel<CustomerDetailsViewModel>(new CustomerDetailsViewModel.NavObject(this.SelectedCustomer));
}
... and presenter will do the rest inside the code triggered by ShowViewModel call. However, in the episode 42 it's shown how to control view model lifetime right from the associated view:
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
VisibleViewModel.IsVisible(false);
if (e.NavigationMode == NavigationMode.Back)
KillableViewModel.KillMe();
}
But if a view model lifetime is controlled by a presenter, shouldn't we try to place KillMe call inside presenter's logic? I know so small piece of code doesn't make much difference but couldn't this be an advantage to put it in presenter's class and reduce code-behind?