Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Real world apps with Xamarin and MVVM

332 views

Published on

With Xamarin now free for everyone, the popularity of the cross-platform framework is increasing rapidly. We’ve now had the time to play around with it, now the time has come to build serious apps with it.
In this session, you’ll learn how a real-world Xamarin application architecture is built, with an emphasis on testability and maintainability. The app we’ll look at is called MyTrains, an application used to book train journeys.
You’ll see an architecture that has proven itself over different projects already. The architecture is using the MvvmCross framework. You’ll see how the architecture is built from the ground up, starting with model, the repositories and the services. On top of that, we’ll build the view models which will be used by the views in the iOS and Android apps. Along the way, you’ll see how MvvmCross uses data binding and commanding and how navigation is handled in MVVM
You’ll walk away with an example of how real applications in Xamarin should be built. You’ll be able to use this as your starting point for your next Xamarin application.

Published in: Software
  • Be the first to comment

Real world apps with Xamarin and MVVM

  1. 1. Building a real-world cross-platform app with Xamarin and MVVM Gill Cleeren @gillcleeren
  2. 2. Gill Cleeren Microsoft MVP & RD Solution Architect @gillcleeren www.snowball.be gill@snowball.be
  3. 3. Xamarin, HTML5, WPF, social and Windows development http://gicl.me/mypscourses
  4. 4. Overview We’ll start with Looking at the final app Understand the concepts of the architecture Understand MvvmCross And then… We’ll explore the architecture We’ll look at the shared blocks We’ll see the Android and iOS apps And we’ll add some tests And then we’ll all go home. Or get a drink.
  5. 5. The app we’ll be using • My Trains • Works on iOS and Android • Searching train journeys • View journey details • Add to My Journeys • Settings • Based on MvvmCross framework
  6. 6. Code available on GitHub via https://github.com/GillCleeren/MyTrains
  7. 7. Concepts of the architecture
  8. 8. Data Binding
  9. 9. UI Element UI Property Object Property Data Binding 3 4 1 2 Binding target Binding source
  10. 10. The Data Context From: London To: Manchester Departure: 11:00 Save Object
  11. 11. We can bind to… Single objects Collections
  12. 12. <TextView android:textSize="18dp" local:MvxBind="Text SelectedJourney.JourneyDate" /> Binding in Android (using MvvmCross)
  13. 13. var set = this.CreateBindingSet<JourneyDetailView, JourneyDetailViewModel>(); set.Bind(DepartureDateLabel) .To(vm => vm.SelectedJourney.JourneyDate)); Binding in iOS (using MvvmCross)
  14. 14. public class MyModel : INotifyPropertyChanged { private string _myProperty; public string MyProperty { get { return _myProperty; } set { _myProperty = value; PropertyChanged (this, new PropertyChangedEventArgs("MyProperty"); } } public event PropertyChangedEventHandler PropertyChanged; } Change notifications
  15. 15. Binding modes OneTime OneWay TwoWay OneWayToSource
  16. 16. <EditText local:MvxBind="Text NumberOfTravellers, Mode=TwoWay" /> Binding modes in code
  17. 17. public class DateTimeToDayConverter : MvxValueConverter<DateTime, string> { protected override string Convert(DateTime value, Type targetType, object parameter, CultureInfo culture) { return value.ToString("MMM dd, yyyy"); } } <TextView local:MvxBind="Text SelectedJourney.JourneyDate, Converter=DateTimeToDay" /> Converters
  18. 18. And now for something completely MVVM!
  19. 19. MVVM, c’est quoi? Architectural pattern Based on MVC Data binding & Commanding XAML
  20. 20. What we all did when we were young… Write code in code-behind… Lots of it. Data Model View “View” code Code-Behind Event Handlers
  21. 21. Writing testable code however, is becoming the norm. Finally. Courtesy of MVVM. Data Model View “View code” Code-Behind View Model State + Operations Change notification Data-binding and commands
  22. 22. public class JourneyDetailViewModel : MvxViewModel, IJourneyDetailViewModel { public Journey SelectedJourney { get { return _selectedJourney; } set { _selectedJourney = value; RaisePropertyChanged(() => SelectedJourney); } } public MvxCommand CloseCommand { get { return new MvxCommand(() => Close(this)); } } } Sample view model
  23. 23. The powers of MvvmCross Open source Promotes sharing of code iOS, Android, XF, WPF…
  24. 24. MvvmCross features Data binding IOC built-in Rich support for plugins
  25. 25. Exploring the architecture
  26. 26. Core project (Shared) UI projects Repositories Data Services View Models Other services Models Remote service iOS Android Windows UWP Mvvm Cross MvvmCross
  27. 27. Core project (Shared) UI projects Repositories Data Services View Models Other services Models Remote service iOS Android Windows UWP Mvvm Cross MvvmCross
  28. 28. Unit test project Shared code Android project iOS project Solution and Projects
  29. 29. The Core Project Portable class library Shared Project Standard Library Project
  30. 30. Required NuGet Packages
  31. 31. Demo Looking at the solution and the MvvmCross packages
  32. 32. Exploring the Core project
  33. 33. Important classes to start with… App AppStart Demo
  34. 34. Model Classes POCO Client-side model Sometimes needs to be mapped
  35. 35. public class User { public int UserId { get; set; } public string UserName { get; set; } public string Email { get; set; } public string Password { get; set; } } Sample model
  36. 36. Repository layer Actual data retrieval Layer between data and app CRUD-based Single model Asynchronous Maps to local models
  37. 37. public class SavedJourneyRepository : ISavedJourneyRepository { public async Task<IEnumerable<SavedJourney>> GetSavedJourneyForUser(int userId) { ... } public async Task AddSavedJourney (int userId, int journeyId, int numberOfTravellers) { ... } } Sample repository
  38. 38. Services Layer between repo and VMs Unit of functionality Business rules Abstractions with interfaces
  39. 39. public class CityDataService: ICityDataService { public async Task<List<City>> GetAllCities() { ... } public async Task<City> GetCityById(int cityId) { ... } } Sample data service
  40. 40. Demo Exploring the Core project
  41. 41. IOC & Service location in MvvmCross Central location for dependencies Useful for testing Built into MvvmCross
  42. 42. Mvx.RegisterSingleton<ICityDataService> (new CityDataService()); var cityDataService = Mvx.Resolve<ICityDataService>(); Registering with the IOC container
  43. 43. public class UserDataService: IUserDataService { private readonly IUserRepository _userRepository; public UserDataService(IUserRepository userRepository) { _userRepository = userRepository; } } Registering with the IOC container
  44. 44. We can use the IOC container to plug a different implementation into the core project per platform.
  45. 45. Demo The Mvx service locator in use
  46. 46. View Models State Operations
  47. 47. public class JourneyDetailViewModel : MvxViewModel, IJourneyDetailViewModel { public Journey SelectedJourney { get { return _selectedJourney; } set { _selectedJourney = value; RaisePropertyChanged(() => SelectedJourney); } } } View Model
  48. 48. public class JourneyDetailViewModel : MvxViewModel, IJourneyDetailViewModel { public MvxCommand CloseCommand { get; set; } public JourneyDetailViewModel() { CloseCommand = new MvxCommand(() => { Close(this); }); } } View Model
  49. 49. NavigateToSearchJourneyCommand = new MvxCommand(() => ShowViewModel<SearchJourneyViewModel>()); ViewModel navigation
  50. 50. Demo View Models
  51. 51. Moving to the Android app
  52. 52. The Android Project
  53. 53. Packages in the Android app MvvmCross Plugins Xamarin Android support packages
  54. 54. Starting the actual Android app Android app Core Setup App Initialize() AppStart() First VM()
  55. 55. public class Setup: MvxAndroidSetup { public Setup(Context applicationContext) :base(applicationContext) { } protected override IMvxApplication CreateApp() { return new Core.App(); } } ViewModel navigation
  56. 56. [Activity( Label = "@string/ApplicationName", MainLauncher = true)] public class SplashScreen : MvxSplashScreenActivity { public SplashScreen() : base(Resource.Layout.SplashScreen) { } } Splash screen
  57. 57. Demo Looking at the Android app
  58. 58. [MvxFragment(typeof(MainViewModel), Resource.Id.content_frame, true)] [Register("mytrains.droid.views.JourneyDetailsFragment")] public class JourneyDetailsFragment: MvxFragment<JourneyDetailViewModel> { public override View OnCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { base.OnCreateView(inflater, container, savedInstanceState); return this.BindingInflate(Resource.Layout.JourneyDetailsView, null); } } Detail page (fragment)
  59. 59. <Mvx.MvxListView android:id="@+id/searchresults_list” local:MvxItemTemplate="@layout/item_journey_search_result" local:MvxBind="ItemsSource Journeys; ItemClick ShowJourneyDetailsCommand" /> List page
  60. 60. Creating the different Android views Demo
  61. 61. Creating the DrawerLayout navigation Main Activity MenuFragment Search Journeys Fragment
  62. 62. Demo Adding the DrawerLayout navigation
  63. 63. And now: iOS
  64. 64. The iOS Project
  65. 65. Packages in the iOS app MvvmCross Plugins
  66. 66. Application Startup iOS app Core Setup App Initialize() AppStart() First VM()
  67. 67. public class Setup: MvxIosSetup { public Setup(MvxApplicationDelegate applicationDelegate, UIWindow window) : base(applicationDelegate, window) { _applicationDelegate = applicationDelegate; _window = window; } protected override IMvxApplication CreateApp() { return new App(); } protected override void InitializeIoC() { base.InitializeIoC(); Mvx.RegisterSingleton<IDialogService>(() => new DialogService()); } } Setup
  68. 68. The Application Storyboard
  69. 69. Demo Looking at the iOS app structure
  70. 70. public partial class JourneyDetailView : BaseView { protected JourneyDetailViewModel JourneyDetailViewModel => ViewModel as JourneyDetailViewModel; public JourneyDetailView(IntPtr handle) : base(handle) { } protected override void CreateBindings() { } } Sample view controller
  71. 71. Building Blocks UITableView TableViewSource Cell
  72. 72. Creating the different iOS views Demo
  73. 73. Main View Model Tab Navigation in iOS Search Journey View Model Saved Journeys View Model Settings View Model
  74. 74. Demo Adding the Tab navigation
  75. 75. Working with plug-ins
  76. 76. What are plug-ins for MvvmCross? Add functionality Work because of IOC Can be shared or specific for a platform Extension point NuGet
  77. 77. Existing plugins Database (Sqlite) Email Files Localization Messenger Location
  78. 78. Demo Showing web pages with the Browser plugin
  79. 79. Putting our architecture to the test
  80. 80. Unit tests – Why? Bugs No fear of change Better software
  81. 81. Demo Testing the view models and the services
  82. 82. Summary • MVVM and MvvmCross promote reuse • iOS and Android app can share more code • Architecture can be your starting point
  83. 83. Take a look at the code and tweet @gillcleeren for questions or remarks!
  84. 84. And watch the full Pluralsight course via https://www.pluralsight.com/courses/mvvm-based- architecture-xamarin-mobile-apps
  85. 85. Thank you!
  86. 86. Q&A
  87. 87. Building a real-world cross-platform app with Xamarin and MVVM Gill Cleeren @gillcleeren

×