Reputation: 445
I´ve got 2 ViewModels
(ConfigurationViewModel
and EditConfigurationViewModel
). In the ConfigurationViewModel
I've got the following code:
public ConfigurationViewModel()
{
NewConfigCommand = new MvxRelayCommand(DoNewConfig);
EditConfigCommand = new MvxRelayCommand<ConfigurationSet>(DoEditConfig);
}
private void DoNewConfig()
{
this.RequestNavigate<EditConfigurationViewModel>();
}
private void DoEditConfig(ConfigurationSet config)
{
this.RequestNavigate<EditConfigurationViewModel>(new { id = config.Id.ToString() });
}
In the EditConfigurationViewModel I've got the following code:
public EditConfigurationViewModel()
{
Configuration = new ConfigurationSet();
}
public EditConfigurationViewModel(string id)
{
Configuration = ConfigDataStore.GetConfiguration(Guid.Parse(id));
}
What I want to achieve is something very simple... In the ConfigurationViewModel
when the NewConfigCommand
is fired, I want to navigate to the EditConfigurationViewModel
, and use the parameterless constructor. When the EditConfigCommand
is fired I want to use the constructor that receives a string
.
The problem with this code is that no matter what command is fired, the parameterless constructor is allways used and the code never reaches the other constructor.
I did some experiments, by removing the parameterless constructor, and the result was that the other constructor is called and I get the expected result for the EditConfigurationCommand
, but if I try to fire the NewConfigurationCommand
an exception is throw due too the inesxistence of a parameterless constructor (so far so good).
Unfortunately, at this moment I don't have VS2010 installed, so I'm not able to debug through PCL code... I've done some "eye debug" and found this class MvxViewModelLocator
. I think the problem is somewhere here. Maybe in the DoLoad
method when it tries to get the MethodInfo
...
At this point I just wanted to know if I'm doing something wrong or if this is the expected result. Meanwhile I think I'll take a chance on installing VS2010 and pray that it won´t break anything...
Upvotes: 3
Views: 2487
Reputation: 66882
On the PCL debugging issue, why not just add a Win8 or WP7/8 UI - then you can debug through the PCL code...
On the main question - about how to use multiple constructors... I'd suggest you don't.
For me, edit and new are two different views and two different viewmodels - they may share common properties and common layout - but this can be achieved using inheritance, using UserControls, using include
axml, etc.
For an example of what I generally use for new and edit see https://github.com/slodge/MvvmCross/tree/vnext/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/ViewModels
If you do insist on carry on using one viewmodel, then you could consider using a 'magic value' for New - e.g. if Guid.Empty is passed then that means new?
Alternatively, you could just drop your parameterless constructor and could add a default value to the second one:
public EditConfigurationViewModel(string id = null)
{
Guid value;
if (id == null || !Guid.TryParse(id, out value))
{
Configuration = new ConfigurationSet();
}
else
{
Configuration = ConfigDataStore.GetConfiguration(value);
}
}
I think that would work?
Finally, if none of that seems suitable to you, then you could consider overriding the ViewModel construction mechanism.
To help with this, there's a fairly detailed recent post on how to write your own default ViewModelLocator for MvvmCross - see http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html
Using this approach, you could create a much more custom navigation model - or if this is the only special view model, then I suspect you could create a default viewModelLocator like:
public class MyViewModelLocator
: MvxDefaultViewModelLocator
{
public override bool TryLoad(Type viewModelType, IDictionary<string, string> parameterValueLookup,
out IMvxViewModel model)
{
if (viewModelType == typeof(EditConfigurationViewModel))
{
string id;
if (parameterValueLookup.TryGetValue("id", out id))
{
model = new EditConfigurationViewModel(id);
}
else
{
model = new EditConfigurationViewModel();
}
return true;
}
return base.TryLoad(viewModelType, parameterValueLookup, IMvxViewModel model);
}
}
and register that locator in App.cs using:
protected override IMvxViewModelLocator CreateDefaultViewModelLocator()
{
return new MyViewModelLocator();
}
Upvotes: 4