Mvvmcross 6 is a new version of Mvvmcross using Netstandard2 instead of the obsolete PCL libraries. It is also a complete refactoring of the previous versions. Migrating is not as easy as updating nuget. But to prevent further technical debt, you should migrate as soon as possible.
- Upgrade your PCL projects to netstandard2
- Replace all the calls to Mvx.Log (already available in 5)
- Upgrade all your in-house Mvvmcross 5 plugins to 6
- Replace all Mvvmcross 5 nugets and plugins in all your projects
- Fix namespaces and class names
- Fix startup
- Fix ios project
- Fix android project
Upgrade your PCL projects to netstandard2
This is the real first step to take. If you still have a PCL project, you own a 2 years technical debt. So first convert your project to netstandard2.
The same is true for projects containing a package.config file. Migrate these “package.config” projects to “PackageReference” projects. VS2017 now includes a wizard for this: right click on the package.config file and migrate.
Replace all the calls to Mvx.Log (already available in 5)
The logging infrastructure has changed in Mvvmcrss 5, but it keeps the compatibility with Mvx.Log. Mvvmcross 6 removed this compatibility. So make sure you use the new logging system everywhere first.
Note that there is no equivalent of the static method Mvx.Log. Instead you should call Mvx.Resolve<IMvxLog>().Trace() for example.
At this point, your apps should still compile and run fine.
Upgrade all your in-house Mvvmcross 5 plugins to 6
All your Mvvmcross plugins must use Mvvmcross 6, otherwise bad things will happen at runtime. So the first step is to upgrade them. Use this same guide to do it:
- Replace all Mvvmcross 5 nugets and plugins from the solution (see next chapter)
- Remove calls to PresentModalViewController()/NativeModalViewControllerDisappeared as the interface has been removed. Instead you’ll have to manually find a UIView/Activity on which you can attach. This is a real issue with this mvvmcross 6 version, as the code used in the existing plugins is failing in case your app already displays a dialog or a UIAlert window. Here a working code for iOS:
For Android, inherit your plugin from MvxAndroidTask and use base.StartActivityForResult().
Replace all Mvvmcross 5 nugets and plugins from the solution
You should do this in 2 steps: remove all nugets, then add the new ones.
To remove the nugets, you can use the nuget package manager, but it’s much faster to edit the csjproj files by hand and remove the entries. Don’t forget a project, and don’t forget a plugin.
Then use the package manager to add the new Mvvmcross 6 nugets. Note that you now only need a few packages. Most used packages are:
This is the most annoying part. Mvvmcross 6 renamed nearly all namespaces. So lots of “using” lines will be obsolete. In nearly 100% of your source files. Do this one project at a time. Start with the netstandard projects. Finished with the platform projects. After this operation, each project should compile fine.
This will be a pain to change unless you use the Resharper extension. Resharper shows in red the old namepaces (missing), and automatically pops a tooltip to add “missing namespaces” in one single click. Amazing.
Mvx.IocConstruct has been renamed Mvx.IoCConstruct
IMvxMainThreadDispatcher is obsolete and replaced by IMvxMainThreadAsyncDispatcher. The InvokeOnMainThread method is replaced by ExecuteOnMainThreadAsync() which returns a Task.
MvxViewModel contains a new property “Log” of type ‘IMvxLog’. But it requires that the virtual LogProvider property is initialized.
In App.cs, the correct place to navigate your first viewmodel is in your custom MvxAppStart in the NavigateToFirstViewModel() method. In this method use the NavigationService property.
You should not navigate a viewmodel directly in the App.cs’s Initialize() method.
Inherit either from MvxAppStart<YourViewModel>, or from MvxAppStart and override NavigateToFirstViewModel() and register it in you app’s constructor:
Note that this interface has a new method, ResetStart(). On Android, it must be called manually in response to Application.IActivityLifecycleCallbacks.OnActivityDestroyed when the destroyed activity is the root activity of your app (ie: activity.IsTaskRoot is true and typeof(activity)=typeof(yourmainactivity).
Fix iOS project
Remove the boostrap folder (and all bootstrap files). These are not needed anymore.
These special classes needs specific changes if you customized them:
- Setup.cs (if you use a custom one)
- AppPresenter.cs (if you use a custom one, even if it compiles)
- The FinishedLaunching method should not do any custom ini anymore, other than google/firebase and facebook. Move this to InitializePlatformServices in setup.cs.
- If you use a custom Setup class, register it in the new override:
- CreatePresenter has been renamed to CreateViewPresenter.
- InitializePlatformServices is now the only method that runs on the UI thread. All other methods runs on a background thread. Make sure you do UIKit calls only on the UI thread. Especially calls to get the screen size, initialize your app’s theme, but also initialize the Azure AppCenter’s libraries!
- If you need to manually register/initialize plugins or converters, override LoadPlugins(IMvxPluginManager)in App.cs instead.
- PresentModalViewController()/NativeModalViewControllerDisappearedOnItsOwn have been removed from
Fix Android project
Things are quite the same as in iOS, except that :
- If you have a custom android Application class, it must either inherit from the new MvxAndroidApplication class, or your Setup.cs class must override InitializeAndroidCurrentTopActivity and IMvxAndroidCurrentTopActivity should be registered in the IOC.
- The MvxAndroidApplication class has a default RegisterSetup method which calls this.RegisterSetupType<Setup>(typeof(Setup).Assembly); This will initialize the Setup.ViewAssemblies property (which is the list of assemblies where mvvmcross search the views).
Replace all calls to Mvx.Resolve, Mvx.Register and related methods
This is optional as it will only generate warnings (for now).
All these methods have moved into a new container for objects (ioc) and are now accessible through Mvx.IoCProvider.Resolve<T> for example.
You can check other changes on the mvvmcross migration document which completes points not covered by this article: https://www.mvvmcross.com/documentation/upgrading/upgrade-to-mvvmcross-60
Happy coding !
Benjamin Mayrargue, VAPOLIA.
Note: see our fantastic XamSvg and WheelPicker nuget libraries for Xamarin and Forms!