MVVMLight implementations and platforms

What i have

Using MVVMLight, I have some service interfaces declared in a portable project and corresponding implementations in a Windows Phone project (WP8.1 SL). To register implementations, I use SimpleIoc.Default.Register in the Application_Launching method in 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 in the portable project and registers all view models in the IOC container in the static constructor, as the docs say.

 static ViewModelLocator() { ... SimpleIoc.Default.Register<TagColorViewModel>(); ... } 

TagColorViewModel is one of these models. It receives a message before displaying the corresponding view. For example, when you click a tag to change its color, MessengerInstance.Send used, and then the navigation service is used to go to the type of color change of the tag.

 // 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); } 

Actual problem

Since the view model is created in MVVMLight just before its first use through the corresponding view, the message is not accepted by TagColorViewModel (simply because there is no instance of this virtual machine yet).

A possible solution would be to use true as a parameter when registering the view model.

 SimpleIoc.Default.Register<TagColorViewModel>(true); 

This, unfortunately, does not work. The reason is that, as can be seen from the above constructor, TagColorViewModel has a dependency on INavigationService . This, in turn, is registered in the Application_Launching method, which after calling the static constructor of the view model locator. As a result, SimpleIoc cannot create an instance of TagColorViewModel because there is no known INavigationService interface or implementation.

Actual question

How can I solve this problem? In other words: How can I register certain platforms in MVVMLights SimpleIoc so that I can let it instantiate view models while they are registered?

Xamarin seems to be using a decorator to solve such problems, but I don't know 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 registering all the platform-specific services. It works, but I do not think this is the right solution.

 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>(); ... } 
+6
source share
2 answers

One approach might be to register services on the platform during application creation, rather than Application_Launching . This will ensure that all your services are registered as soon as possible. The only caveat is to make sure they happen after calling ServiceLocator.SetLocatorProvider .

0
source

Use a combination of the Xamarin dependency service and MVVMLight. The MVVMLight Register method has an overload where you can write your own function to generate the instance.

Put all your login details in ViewModelLocator as follows:

 SimpleIoc.Default.Register<Service.INavigationService>(() => { return DependencyService.Get<Service.INavigationService>(); }); 

Then go and put the appropriate assembler attributes in your platform-specific service implementation ...

 [assembly: Xamarin.Forms.Dependency(typeof(NavigationService))] 
0
source

Source: https://habr.com/ru/post/987880/


All Articles