What I have
Using MVVMLight, I have some service interfaces that are declared in a portable project and the corresponding implementations in a Windows Phone project (WP8.1 SL). To register the implementations I use SimpleIoc.Default.Register
in the Application_Launching
method within the App
class.
public partial class App : Application
{
...
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
...
// add some platform specific services to the IOC container
SimpleIoc.Default.Register<INavigationService, NavigationServiceWP>(true);
SimpleIoc.Default.Register<ISettingsService, SettingsService>(true);
SimpleIoc.Default.Register<IThemeService, ThemeService>(true);
SimpleIoc.Default.Register<IGeofenceService, GeofenceService>(true);
SimpleIoc.Default.Register<IVersionService, TrialInformation>(true);
SimpleIoc.Default.Register<IPhoneService, PhoneServices>(true);
...
}
...
}
The view model locator is located in the portable project and registers all view models to the IOC container in a static constructor, just as the docs say.
static ViewModelLocator()
{
...
SimpleIoc.Default.Register<TagColorViewModel>();
...
}
The TagColorViewModel
is one of these models. It receives a message before the corresponding view is shown. For example, when a tag is clicked to change its color then MessengerInstance.Send
is used, and afterwards the navigation service is used to navigate to the tag color change view.
// TagViewModel
private void ChangeColor()
{
MessengerInstance.Send(Tag, TagColorViewModel.MessengerToken.SetTag);
_navigationService.Navigate("/UI/Tagging/TagColor.xaml");
}
This message receiver is registered in the constructor.
// TagColorViewModel
[PreferredConstructor]
public TagColorViewModel(INavigationService navigationService)
{
...
// Messages
MessengerInstance.Register<Tag>(this, MessengerToken.SetTag, SetTag);
}
The Actual Problem
Because the view model is created in MVVMLight right before it is used for the first time via its corresponding view, the message is not received by TagColorViewModel
(simply because there is no instance of that VM yet).
A possible solution would be to use true
as parameter when registering the view model.
SimpleIoc.Default.Register<TagColorViewModel>(true);
This unfortunately doesn't work. The reason is that, as can be seen in the constructor above, TagColorViewModel
has a dependency to the INavigationService
. This in turn is registered in the Application_Launching
method, which is after the static constructor of the view model locator is called. The result is that SimpleIoc can't create an instance of TagColorViewModel
because there is no known INavigationService
interface or implementation.
Actual Question
How can I solve this issue? In other words: How can I register platform specific services in MVVMLights SimpleIoc so that I can let it create instances of view models during their registration?
Xamarin seems to use a decorator to solve such issues but I don't know of any comparable construct in MVVMLight.
Xamarin.Forms.Dependency(typeof(PopupService))
Current Workaround
My current workaround is to get an instance that is never used later right after all the platform specific services are registered. It works but I don't think this is the correct solution to that.
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
...
// add some platform specific services to the IOC container
SimpleIoc.Default.Register<INavigationService, NavigationServiceWP>(true);
...
var tcvm = SimpleIoc.Default.GetInstance<TagColorViewModel>();
...
}