Skip to content

Instantly share code, notes, and snippets.

@saamerm
Created March 26, 2021 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saamerm/d21769976efa1bca79891fe4745b36e7 to your computer and use it in GitHub Desktop.
Save saamerm/d21769976efa1bca79891fe4745b36e7 to your computer and use it in GitHub Desktop.
### Steps to perform migration of MvvmCross using PCL
(primarily done is Visual Studio for Mac)
This tutorial migrates
- PCL .Net solution to .NetStandard,
- MvvmCross 5 solution to MvvmCross 7.1,
- Android to AndroidX
#### The beginning
1. Create a new repository, with a Migration suffix
2. Inside it, create a New Blank Native Xamarin Template
3. Make sure it has the exact same name for the solution and the projects
4. Rename the Core project to .ViewModels. Update the SLN and CSPROJ files so that they also point to the renamed ViewModels project
5. Go to the ViewModels project options and update the Project Options->Target Framework to NetStandard2.0. (Migrating to NetStandard2.1 gave me some issues)
1. Since you make the change from PCL to NetStandard, you won’t be needing project.json, app.config, AssemblyInfo.cs files, and the CSProj can just automatically include everything in folders without needing to specify each file
6. Add the latest MvvmCross (7.1.2) and make sure you are able to build iOS and Android with the changes requested by MvvmCross to the ViewModel and UI Projects. I implemented the changes from the MvvmCross sample- TipCalc, and made sure the app builds on both platforms (iOS & Android)
7. If it did, then I committed and pushed my changes
#### Migration of Project 1
1. Right click on the ViewModel solution and say “Add->Files from Folder” and add everything from the ViewModels page, make sure it’s in the right location
2. Add the needed Nuget Packages (ACR Settings, AppCenter, MvvmCross, MvvmCross Plugins-Email/Messenger/Phone/WebBrowser, MvvmValidation, Plugin Mediamanager, Newtonsoft Json, CSharp, Xamarin essentials) - Xamarin essentials can prevent the need of some other plugins like Connectivity and DeviceInfo
3. Add a new “Services” Project with the right name, Target framework, and make sure the ViewModel project uses it as a reference
4. To the Services project, add the needed Nuget Packages (ACR Settings, AppCenter analytics, MvvmCross, MvvmCross Messenger, Newtonsoft Json)
1. Since you make the change from PCL to NetStandard, you won’t be needing project.json, app.config, AssemblyInfo.cs files, and the CSProj can just automatically include everything in folders without needing to specify each file
5. Add the 5th project (Web.FinanceModels) as well, make sure it has the right name, target framework, and its added as a reference to the Services project
6. If using the older `Plugin.Connectivity` anywhere, convert `CrossConnectivity.Current.IsConnected` to `Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.Internet
7. Use Rider to see the total number of errors
8. Over 400 view models
9. Finish fixing the errors to the Services project, once done commit your changes
1. Replace `using MvvmCross.Platform` with just `using MvvmCross`
2. Mvx.Trace stopped working, dont know how to fix yet???
3. Replace `using MvvmCross.Binding.ExtensionMethods` with just `using MvvmCross.Binding.Extensions`
4. Replace `using MvvmCross.Plugins.Messenger` with just `using MvvmCross.Plugin.Messenger`
5. Replace `Settings.Current.x` with `CrossSettings.Current.x coming for Acr.Settings`
6. Replace `using MvvmCross.Core.ViewModels` for Commands to `using MvvmCross.Commands`
#### Then fix the errors in the Core/ViewModel project:
1. Most likely you will have errors in the Navigation because of the riddance of some functions(Close, ShowViewModel) to start using Navigator.Close and Navigator.Navigate
2. The way data is passed into a view model changed because of the lack of usage of “MvxBundle”- to start using Parameters, requiring the Prepare lifecycle function
3. All the IMvxCommands and MvxCommands will need a “using MvvmCross.Commands;” in the file or just add “MvvmCross.Commands.” added before it. Rider has a neat function that adds all the required using statements for errors that can be resolved in that way.
4. The CSharp nuget was needed because of some issue in the PRAPageQuestions and Answer that said I needed the CSharp DLL
5. Any pages using media is a pain, because the events have changed, and some properties are unavailable. All Status suffixes have changed to State. Left some to be fixed later
6. Mvx.Trace stopped working so for now I just added Console.WriteLine. For stuff like that I commented that code out along with a “//TODO: Fix” comment
7. Once done with all 5000+ errors you will want to build on iOS but it will give you this error: "Failed to resolve assembly..."
8. You will need to add the Nuget Packages there (ACR Settings, AppCenter, MvvmCross, MvvmCross Plugins-Email/Messenger/Phone/WebBrowser, Newtonsoft Json, MvvmValidation, Plugin Mediamanager, Xamarin Essentials)
9. Then try to build, if successful, commit your changes
10. Over 400 ViewModel changes
#### iOS Project changes:
1. Took the Similar to the stuff above, you ll need to fix errors:
1. Replace `using MvvmCross.Binding.iOS.Views;` with `using MvvmCross.Platforms.Ios.Binding.Views;`
2. Replace `using MvvmCross.Core.ViewModels` for Commands to `using MvvmCross.Commands`
3. Replace `using MvvmCross.Core.ViewModels` for MvxObservableCollection to `using MvvmCross.ViewModels`
4. Replace `using using MvvmCross.iOS.Support.Views;` with `using MvvmCross.Platforms.Ios.Views;`
5. Replace `using MvvmCross.Platform.Converters` with just `using MvvmCross.Converters`
6. Replace `using MvvmCross.Binding.ExtensionMethods` with `using MvvmCross.Binding.Extensions`
7. Removed `using MvvmCross.Platform.Core` and added `using MvvmCross.Binding.BindingContext` for `IMvxBindingContext` and `using MvvmCross.ViewModels` for `IMvxInteraction`, and `using MvvmCross.Base` for `MvxValueEventArgs` or `IMvxDataConsumer`
8. Replace `using MvvmCross.Platform;` to `using MvvmCross;` for `Mvx.Resolve`
9. Replace `using MvvmCross.Core.Navigation;` to `using MvvmCross.Navigation;`
2. Removed the Bootstrap files since its not needed anymore, and remove references to it
3. Updated the delicate AppDelegate file to work with the updated AppStart
4. Also updated the Setup.cs file as needed
5. Updated the DebugTrace.cs to inherit from IMvxLog instead of IMvxTrace and fixed it up
6. Since we are using the older `Plugin.Connectivity` anywhere, convert `CrossConnectivity.Current.IsConnected` to `Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.Internet
7. More than 500 Views and ViewController changes, but who’s counting
8. No changes on audio recording player were needed on the iOS UI side
9. If you are using a custom iOS view presenter (using a class that inherits from MvxIosViewPresenter), you might be in for a hard time. Especially if you are using the `view` from this override: Show(IMvxIosView view, MvxViewModelRequest request), because that override is not available anymore. You only have access to Show(MvxViewModelRequest request). I was able to use this new override instead CreateOverridePresentationAttributeViewInstance(Type viewType) by just saying `var view = base.CreateOverridePresentationAttributeViewInstance(viewType);` to update attributes on the UIViewController
10. You might also have section header expand issues with TableSources inheriting from MvxExpandableTableViewSource. Upon debugging I realized, MvvmCross adds a hidden button automatically, that knows to tap to expand. I noticed that this class was using a container UIView to put labels and images inside. Upon removing the container, it started working again.
11. Some of your TableViewSources might be using a variation of `ItemsSource.ElementAt(i).IsExpanded = false;` which is not available anymore. You can fix it by using this instead `var group = (ItemsSource as IList)[i] as DocumentListGroup; if (group != null) group.IsExpanded = false;`
#### Android to AndroidX and MvvmCross
1. Had a choice to just migrate MvvmCross to the latest version, but I took the risky challenge and decided to migrate to AndroidX as well.
2. Go to Rider and just Right Click and say add all import statements in solution and it fixes >5000 errors
3. Took the Similar to the stuff above, you ll need to fix errors:
1. Replace `MvvmCross.Binding.Droid.Target;` with `using AndroidX.AppCompat.Widget`
2. Replace `using Android.App` and `using Android.Widget` with `using AndroidX.AppCompat.Widget`, but for the `[Activity` Attribute you can convert those to `[Android.App.Activity`
3. Replace `using MvvmCross.Droid.Support.V7.AppCompat;` with `using MvvmCross.Platforms.Android.Views.AppCompat`
4. Replace `using MvvmCross.Droid.Views;` with `using MvvmCross.Views;`
5. Replace `Android.Support.V4.Content.Res` with `using AndroidX.Core.Content.Resources`
6. Replace `Application.Context.x` with `CrossCurrentActivity.Current.AppContext.x` using the Plugin.CurrentActivity in several places
7. Replace `using Toolbar = Android.Support.V7.Widget.Toolbar;` to `using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
8. Replace `using Android.Support.V4.Widget;` and `using Android.Support.V4.View;` as needed with `using AndroidX.Core.View;` `using AndroidX.DrawerLayout.Widget;` or `using MvvmCross.Platforms.Android.Views;`
9. Replace `using MvvmCross.Core.ViewModels` for Commands to `using MvvmCross.Commands`
10. Replace `using MvvmCross.Core.ViewModels` for MvxObservableCollection to `using MvvmCross.ViewModels`
11. Replace `using MvvmCross.Platform.Converters` with just `using MvvmCross.Converters`
12. Replace `using MvvmCross.Binding.ExtensionMethods` with `using MvvmCross.Binding.Extensions`
13. Removed `using MvvmCross.Platform.Core` and added `using MvvmCross.Binding.BindingContext` for `IMvxBindingContext` and `using MvvmCross.ViewModels` for `IMvxInteraction`, and `using MvvmCross.Base` for `MvxValueEventArgs` or `IMvxDataConsumer`
14. Replace `using MvvmCross.Platform;` to `using MvvmCross;` for `Mvx.Resolve`
15. Replace `using MvvmCross.Core.Navigation;` to `using MvvmCross.Navigation;`
16. Replace `using Plugin.MediaManager.ExoPlayer;` and `using Plugin.MediaManager` with `using MediaManager;`
17. Replace `using MvvmCross.Binding.Droid.BindingContext;` with `using MvvmCross.Platforms.Android.Binding.BindingContext;`
18. Replace `using MvvmCross.Binding.Droid.Views;` with `using MvvmCross.Platforms.Android.Binding.Views;`
19. Replace `using MvvmCross.Droid.Support.V7.RecyclerView` with `using MvvmCross.DroidX.RecyclerView` for which you likely need to install the MvvmCross.DroidX.RecyclerView nuget
20. Replace `using MvvmCross.Droid.Views.Attributes;` with `using MvvmCross.Platforms.Android.Presenters.Attributes;`
21. Replace `using MvvmCross.Droid.Support.V4` with `using MvvmCross.Platforms.Android.Views.Fragments;` for Fragments or sometimes with `using MvvmCross.DroidX;`
22. Most of my activities required adding `using AndroidX.Lifecycle;`
23. I also needed to add `using Google.Android.Material.BottomSheet;` and `using Google.Android.Material.Snackbar;` in some classes
24. As a personal choice, I converted the MvxAppCompatSpinner to MvxSpinner, and that layout also needed fixing
4. Update the MvxViewPagerFragmentInfo, since it now requires passing a MvxViewModelRequest instead of just the ViewModel. Passing in parameters is a little different now. I was kind of stuck there, looking at the docs https://github.com/osipyonok/WORKING_MDPAGE/blob/d1d955253b2ec09a13caeb8caf188e268732941f/TestProjects/Navigation/RoutingExample.Core/RoutingFacades/PrePopulateRoutingFacade.cs but you can’t pass byte data across, only string https://stackoverflow.com/questions/48772210/passing-data-to-fragment-viewmodel-mvvmcross. Luckily MvxViewModelInstanceRequest is a type of MvxViewModelRequest which will allow you to pass in the ViewModel instance and that makes it a breeze. Thanks @Cheesebaron for that tip!
1. Some of these files will still break and might give you an System.Reflection.AmbiguousMatchFound exception crash, and fixing that can also be difficult
5. Removed the Bootstrap files since its not needed anymore, and remove references to it
6. Converting the startup to the new style
7. Converting the log in debugtrace
8. Since we are using the older `Plugin.Connectivity` anywhere, convert `CrossConnectivity.Current.IsConnected` to `Xamarin.Essentials.Connectivity.NetworkAccess == Xamarin.Essentials.NetworkAccess.Internet
9. More than 70 Fragments, Activities and Layout file changes, but I stopped counting a long time ago
10. Updated the WebView Client and all the dialogs including the AlertDialog
11. Quite a few changes on audio recording player were needed on the Android UI side
12. Convert the classes that inherit from DialogFragment to start inheriting from MvxDialog instead. Now the dialog.Show will need a SupportFragmentManager instead. This step might cause you some tricky icky issues
13. For your dialogs, if you are using EnsureBindingContextSet(savedState), you can use this instead this.EnsureBindingContextIsSet();
##### In your layout & menu files, change and around the app
1. android.support.v4.widget.DrawerLayout to androidx.drawerlayout.widget.DrawerLayout
2. android.support.v4.view.ViewPager to androidx.viewpager.widget.ViewPager
3. android.support.v4.widget.NestedScrollView to androidx.core.widget.NestedScrollView
4. MvvmCross.Droid.Support.V4.MvxSwipeRefreshLayout to MvvmCross.DroidX.MvxSwipeRefreshLayout
5. MvvmCross.Droid.Support.V7.RecyclerView.MvxRecyclerView to MvvmCross.DroidX.RecyclerView.MvxRecyclerView
6. android.support.v7.widget.AppCompatButton to androidx.appcompat.widget.AppCompatButton
7. android.support.v7.widget.SwitchCompat to androidx.appcompat.widget.SwitchCompat
8. android.support.v7.widget.SearchView to SearchView (though I didn’t test to see if there’s an AndroidX version)
9. android.support.v7.widget.Toolbar to androidx.appcompat.widget.Toolbar
10. android.support.v7.widget.CardView to androidx.cardview.widget.CardView
11. android.support.design.widget.CoordinatorLayout to androidx.coordinatorlayout.widget.CoordinatorLayout
12. android.support.design.widget.AppBarLayout to com.google.android.material.appbar.AppBarLayout
13. android.support.design.widget.TextInputLayout to com.google.android.material.textfield.TextInputLayout
14. android.support.design.widget.TextInputEditText to com.google.android.material.textfield.TextInputEditText
15. android.support.design.widget.TabLayout to com.google.android.material.tabs.TabLayout
16. android.support.design.widget.FloatingActionButton to com.google.android.material.floatingactionbutton.FloatingActionButton
17. android.support.design.widget.NavigationView to com.google.android.material.navigation.NavigationView
18. layout_behavior="android.support.design.widget.BottomSheetBehavior" to com.google.android.material.bottomsheet.BottomSheetBehavior
19. Fix the legacy app storage permissions, an Android 10 requirement if you are using the older way of downloading files
20. A strange one is if you are using MvxFrameControl, you have to switch it from MvvmCross.Binding.Droid.Views.MvxFrameControl to MvvmCross.Platforms.Android.Binding.Views.MvxFrameControl
21. In any menus, if you are using actionViewClass=“SearchView”, change that value to “androidx.appcompat.widget.SearchView”. This is a rather odd one.
22. And so on
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment