Google Getting Started With Xamarin Forms FreshMVVM Framework (C# - Xaml) | SubramanyamRaju Xamarin & Windows App Dev Tutorials

Sunday 25 March 2018

Getting Started With Xamarin Forms FreshMVVM Framework (C# - Xaml)

Introduction:
FreshMvvm is a super light Mvvm Framework designed specifically for Xamarin.Forms. It is designed to be Easy, Simple and Flexible. In my previous article, I was written an article about storing list of contacts in SQLite database with Xamarin.Forms default MVVM. In this tutorial we will achieve the same Xamarin.Forms application with FreshMvvm framework.

Requirements:
  • This article source code was prepared by using Visual Studio Community for Mac (7.4). And it is better to install latest visual studio updates from here.
  • This sample project is Xamarin.Forms PCL project and tested in Android emulator and iOS simulators.
  • MVVM Framework: Used FreshMVVM framework Nuget package version is 2.2.4
  • Storage: Used SQLite.Net-PCL Nuget package version is 3.1.1
  • Validation: Used FluentValidation Nuget Package version is V7.5.2.
Description:
Like my previous SQLite article , here we will build same application with FreshMVVM framework in Xamarin.Forms with below functionality.
  • Add Contact (AddContactPage, AddContactVPageModel): Insert new contact details to SQLite database. Also will have a option to "View All Contacts" if contacts exist in database.
  • Contact List (ContactListPage, ContactListPageModel): Read all contacts from SQLite and displaying contact list. Also will have a option to delete all/add the contact.
  • Contact Details (ContactDetailsPage, ContactDetailsPageModel): Read specific contact from SQLite and showing full information for the same. Also will have a option to delete/update the contact.
So this article can explain you below concepts:
1. FreshMVVM Introduction
2. How to create Xamarin.Forms PCL project with Visual Studio for Mac?
3. How to setup Xamarin.Forms PCL project with FreshMVVM framework?
4. How to setup SQLite and perform SQLite operations in Xamarin.Forms PCL project?
5. How to validate Contact Details with Fluent Validation before data insert to database?
6. How to register interfaces with Fresh IOC?
7. How to create PageModels with FreshMVVM in Xamarin.Forms?
8. How to create Pages and bind with PageModels in FreshMVVM?
9. How to use FreshMvvm built-in navigation class to define the start page for the application?

1. FreshMVVM Introduction
The reason to say FreshMVVM is designed for Xamarin.Forms is because it plays on Xamarin.Forms strengths and fills in only the missing parts. It has a requirement for Xamarin.Forms and therefore is smart and can do thing such as wiring up the BindingContext and Page events.
MVVMFresh is having so many cool features like below:
  • Built in FreshIOC Container.
  • Automatic wiring of BindingContext.
  • Built in Navigation containers for SimpleNavigation, Tabbed and MasterDetail. Also having basic core methods like to display alert.
  • Automatic wiring of Page events (Ex: ViewIsAppearing).
  • PageModel Constructor Injection.
This Framework, while simple, is also powerful and uses a convention over configuration style.

Note different to standard naming conventions, FreshMvvm uses Page and PageModel instead of View and ViewModel, this is inline with Xamarin.Forms using Pages.
And we must follow below rules to use FreshMVVM.
  • A Page must have a corresponding PageModel, with naming important so a AddContactPageModel must have a AddContactPage.
  • The BindingContext on the page will be automatically set with the Model.
  • A PageModel can have a Init method that takes a object.
  • A PageModel can have a ReverseInit method that also take a object and is called when a model is popped with a object.
  • PageModel can have dependencies automatically injected into the Constructor
FreshMVVM - Core Methods:
Each PageModel will have a property called "CoreMethods’" which is automatically filled when a PageModel is pushed and the basic functions that most apps need like Displaying Alert, Pushing, Pop Model etc.




  • public interface IPageModelCoreMethods  
  • {  
  •    Task DisplayAlert (string title, string message, string cancel);  
  •    Task<string> DisplayActionSheet (string title, string cancel, string destruction, params string[] buttons);  
  •    Task<bool> DisplayAlert (string title, string message, string accept, string cancel);  
  •    Task PushPageModel<T>(object data, bool modal = false) where T : FreshBasePageModel;  
  •    Task PopPageModel(bool modal = false);  
  •    Task PopPageModel(object data, bool modal = false);  
  •    Task PushPageModel<T>() where T : FreshBasePageModel;  
  • }  
  • Navigation between Pages
    FreshMVVM itself has navigation methods to make navigation between the pages.
    Use PushPageModel for pushing the page in the navigation stack or goto next page instead of PushAsync in normal MVVM.
    1. await CoreMethods.PushPageModel<AddContactPageModel>();    
    Above code equivalent to the following normal mvvm navigation .
    1. Navigation.PushAsync(new AddContactPage());   
    Use PopPageModel for popping the page from navigation stack instead of PopAsync in normal MVVM
    1. await CoreMethods.PopPageModel();    
    It is equivalent to the following normal mvvm.
    1. Navigation.PopAsync();    
    Display Alert
    1. await CoreMethods.DisplayAlert("Contact Details""Update Contact Details""OK""Cancel");  
    Inversion of Control (IOC)
    We don’t need to include our own IOC container, FreshMvvm comes with a IOC container built-in. It’s using TinyIOC underneath, but with different naming to avoid conflicts. 
    For example to Register IContactRepository interface with ContactRepository class.
    1. //Interface rgistration with FreshIOC  
    2. FreshIOC.Container.Register<IContactRepository, ContactRepository>();  
    PageModel – Constructor Injection
    When PageModels are pushed services that are in the IOC container can be pushed into the Constructor.
    For example in AddContactPageModel constructor, if we pass above IContactRepository interface as parameter and this interface will take implementation from ContactRepository class which was registered by IOC.
    1. public class AddContactPageModel : FreshBasePageModel {  
    2.   
    3.        public IContactRepository _contactRepository;  
    4.   
    5.         public BaseContactPageModel(IContactRepository contactRepository){  
    6.             _contactRepository = contactRepository;  
    7.         }  
    8. }  

    2. How to create Xamarin.Forms PCL project using Visual studio for Mac?
    First we need to create the new Xamarin.Forms project. 
    • Launch Visual Studio for Mac.
    • On the File menu, select New Solution.
    • The New Project dialog appears. In the left pane Multiplatform App Xamarin.Forms > Blank Forms App and click on Next.
    • Enter your App Name (Ex: FreshMvvmSample). Select Target Platforms to Android & iOS and Shared Code to Portable Class Library  after that click on Next button.



    • You can choose your project location like below and Create new project.


    And project structure will be.
    • FreshMVVMSample: It is for PCL shared code.
    • FreshMVVMSample.Droid: It is for Android.
    • FreshMVVMSample.iOS: It is for iOS.
    3. How to setup Xamarin.Forms PCL project with FreshMVVM framework?
    After creating Xamarin.Forms application, We need add FreshMVVM Nuget Package to our PCL project.
    So right click on FreshMVVMSample project Packages and click on Add Packages.

    After that Add Packages dialog window will open, search for "FreshMVVM" and click on Add Package like below.


    After that above package will add to PCL project like below.

    4. How to setup SQLite and perform SQLite operations in Xamarin.Forms PCL project?
    Now we need a managed way to access SQLite database. For that we need to add relevant nuget package name is SQLite.Net-PCL to PCL, Android & iOS projects. SQLite.Net-PCL is a .NET wrapper around SQLite that will allow us to access the native SQLite functionality from a Xamarin.Forms PCL or shared project.
    So right click on your PCL project Packages and click on Add Packages. After that Add Packages dialog window will open, search for "SQLite.Net-PCL" and click on Add Package like below.
    After that above package will add to your PCL project like below.

    Also please add above package to FreshMvvmSample.Droid and FreshMvvmSample.iOS projects by following same above PCL project steps. And make sure same FreshMVVM version package should add to Android and iOS project Packages folder like below.
    We completed the SQLite setup for our xamarin forms project. So it is time to perform all SQLite(Create, Read, Update, Delete, Insert) operations. But before that even tough the "SQLite.Net-PCL" package will provide us the functionality of manipulating the SQLite database, it can’t automatically initialize the database connection object as the location of the database file varies on different platforms. So in order to solve this issue we will use dependency service to load the database file in connection object and please follow below few steps.
    Step 1: Create Interface (ISQLite) in PCL.
    We are following FreshMVVM design pattern. And here we will place helpers in Helpers folder. So right click on your project name FreshMvvmSample => Add => New Folder name is "Helpers". After that right click on your newly created the folder => Add => New File => General => Empty Interface and name it ISQLite and add below code:






  • using System;  
  • using SQLite.Net;  
  •   
  • namespace FreshMvvmSample.Helpers  
  • {  
  •     public interface ISQLite  
  •     {  
  •         SQLiteConnection GetConnection();  
  •     }  
  • }  

  • Step 2: Android Implementation for ISQLite.
    In FreshMvvmSample.Droid project, create folder "Implementations" and create class "AndroidSQLite". After that add below code:
    1. using System.IO;  
    2. using SQLite.Net;  
    3. using FreshMvvmSample.Droid.Implementaions;  
    4. using FreshMvvmSample.Helpers;  
    5.   
    6. [assembly: Xamarin.Forms.Dependency(typeof(AndroidSQLite))]  
    7. namespace FreshMvvmSample.Droid.Implementations {  
    8.     public class AndroidSQLite : ISQLite {  
    9.         public SQLiteConnection GetConnection() {  
    10.             string documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);  
    11.   
    12.             // Documents folder  
    13.             var path = Path.Combine(documentsPath, DatabaseHelper.DbFileName);  
    14.             var plat = new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid();  
    15.             var conn = new SQLiteConnection(plat, path);  
    16.   
    17.             // Return the database connection  
    18.             return conn;  
    19.         }  
    20.     }  
    21. }  
    Step 3: iOS Implementation for ISQLite.
    In FreshMvvmSample.iOS project, create folder "Implementations" and create class "iOSSQLite". After that add below code:
    1. using System;  
    2. using System.IO;  
    3. using Xamarin.Forms;  
    4. using SQLite.Net;  
    5. using FreshMvvmSample.Helpers;  
    6. using FreshMvvmSample.iOS.Implementaions;  
    7.   
    8. [assembly: Dependency(typeof(IOSSQLite))]  
    9. namespace FreshMvvmSample.iOS.Implementations {  
    10.     public class IOSSQLite : ISQLite {  
    11.         public SQLiteConnection GetConnection() {  
    12.             string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder  
    13.             string libraryPath = Path.Combine(documentsPath, "..""Library"); // Library folder  
    14.             var path = Path.Combine(libraryPath, DatabaseHelper.DbFileName);  
    15.             // Create the connection  
    16.             var plat = new SQLite.Net.Platform.XamarinIOS.SQLitePlatformIOS();  
    17.             var conn = new SQLiteConnection(plat, path);  
    18.             // Return the database connection  
    19.             return conn;  
    20.         }  
    21.     }  
    22. }  
    Step 4: Performing SQLite operations with Database Helper class in PCL
    In FreshMvvmSample PCL project, create a class in Helpers folder that should have methods to perform SQLite operation (create, insert, delete, read, update).
    1. using SQLite.Net;  
    2. using Xamarin.Forms;  
    3. using System.Collections.Generic;  
    4. using System.Linq;  
    5. using FreshMvvmSample.Models;  
    6. using System;  
    7.   
    8. namespace FreshMvvmSample.Helpers {  
    9.     public class DatabaseHelper {  
    10.           
    11.         static SQLiteConnection sqliteconnection;  
    12.         public const string DbFileName = "Contacts.db";  
    13.   
    14.         public DatabaseHelper() {  
    15.             sqliteconnection = DependencyService.Get<ISQLite>().GetConnection();  
    16.             sqliteconnection.CreateTable<ContactInfo>();  
    17.         }  
    18.   
    19.         // Get All Contact data      
    20.         public List<ContactInfo> GetAllContactsData() {  
    21.             return (from data in sqliteconnection.Table<ContactInfo>()  
    22.                     select data).ToList();  
    23.         }  
    24.   
    25.         //Get Specific Contact data  
    26.         public ContactInfo GetContactData(int id) {  
    27.             return sqliteconnection.Table<ContactInfo>().FirstOrDefault(t => t.Id == id);  
    28.         }  
    29.   
    30.         // Delete all Contacts Data  
    31.         public void DeleteAllContacts() {  
    32.             sqliteconnection.DeleteAll<ContactInfo>();  
    33.         }  
    34.   
    35.         // Delete Specific Contact  
    36.         public void DeleteContact(int id) {  
    37.             sqliteconnection.Delete<ContactInfo>(id);  
    38.         }  
    39.   
    40.         // Insert new Contact to DB   
    41.         public void InsertContact(ContactInfo contact) {  
    42.             sqliteconnection.Insert(contact);  
    43.         }  
    44.   
    45.         // Update Contact Data  
    46.         public void UpdateContact(ContactInfo contact) {  
    47.             sqliteconnection.Update(contact);  
    48.         }  
    49.     }  
    50. }  
    In above SQLite helper class, we created queries for ContactInfo Table means that we need to create ContactInfo class that should have columns.
    So create Models folder in PCL and add below Table class.
    1. using System;  
    2. using SQLite.Net.Attributes;  
    3.   
    4. namespace FreshMvvmSample.Models  
    5. {  
    6.     [Table("ContactInfo")]  
    7.     public class ContactInfo  
    8.     {  
    9.         [PrimaryKey, AutoIncrement]  
    10.         public int Id { getset; }  
    11.         public string Name { getset; }  
    12.         public string Age { getset; }  
    13.         public string Gender { getset; }  
    14.         public DateTime DOB { getset; }  
    15.         public string Address { getset; }  
    16.         public string MobileNumber { getset; }  
    17.     }  
    18. }  
    Please note that in above class, Id property is marked as the Primary Key and AutoIncrement which will helpful for contact row identification.
    Step 5: Create interface for ContactInfo Table operations
    We will create service that will talk to only ContactInfo Table. So create Services folder in PCL and add below IContactRepository interface
    1. using System;  
    2. using System.Collections.Generic;  
    3. using FreshMvvmSample.Models;  
    4.   
    5. namespace FreshMvvmSample.Services  
    6. {  
    7.     public interface IContactRepository  
    8.     {  
    9.         List<ContactInfo> GetAllContactsData();  
    10.   
    11.         //Get Specific Contact data  
    12.         ContactInfo GetContactData(int contactID);  
    13.   
    14.         // Delete all Contacts Data  
    15.         void DeleteAllContacts();  
    16.   
    17.         // Delete Specific Contact  
    18.         void DeleteContact(int contactID);  
    19.   
    20.         // Insert new Contact to DB   
    21.         void InsertContact(ContactInfo contact);  
    22.   
    23.         // Update Contact Data  
    24.         void UpdateContact(ContactInfo contact);  
    25.     }  
    26. }  
    And after that create a class that should implement above interface.
    1. using System.Collections.Generic;  
    2. using FreshMvvmSample.Helpers;  
    3. using FreshMvvmSample.Models;  
    4.   
    5. namespace FreshMvvmSample.Services  
    6. {  
    7.     public class ContactRepository : IContactRepository  
    8.     {  
    9.         DatabaseHelper _databaseHelper;  
    10.         public ContactRepository(){  
    11.             _databaseHelper = new DatabaseHelper();  
    12.         }  
    13.   
    14.         public void DeleteContact(int contactID)  
    15.         {  
    16.             _databaseHelper.DeleteContact(contactID);  
    17.         }  
    18.   
    19.         public void DeleteAllContacts()  
    20.         {  
    21.             _databaseHelper.DeleteAllContacts();  
    22.         }  
    23.   
    24.         public List<ContactInfo> GetAllContactsData()  
    25.         {  
    26.             return _databaseHelper.GetAllContactsData();  
    27.         }  
    28.   
    29.         public ContactInfo GetContactData(int contactID)  
    30.         {  
    31.             return _databaseHelper.GetContactData(contactID);  
    32.         }  
    33.   
    34.         public void InsertContact(ContactInfo contact)  
    35.         {  
    36.             _databaseHelper.InsertContact(contact);  
    37.         }  
    38.   
    39.         public void UpdateContact(ContactInfo contact)  
    40.         {  
    41.             _databaseHelper.UpdateContact(contact);  
    42.         }  
    43.     }  
    44. }  
    5. How to validate Contact Details with Fluent Validation before data insert to database?
    It will be always good to validate details before save them to database. In this article we are validating ContactInfo table information before inserting into SQLite. Please read to understand how to validate particular class object with FluentValidation from this article.
    In FreshMvvmSample PCL project, we have to add ContactValidator class in Validator folder.
    1. using FluentValidation;  
    2. using FreshMvvmSample.Models;  
    3.   
    4. namespace FreshMvvmSample.Validator  
    5. {  
    6.     public class ContactValidator : AbstractValidator<ContactInfo>    
    7.     {    
    8.         public ContactValidator()    
    9.         {    
    10.             RuleFor(c => c.Name).Must(n=>ValidateStringEmpty(n)).WithMessage("Contact name should not be empty.");  
    11.             RuleFor(c => c.MobileNumber).NotNull().Length(10);  
    12.             RuleFor(c => c.Age).Must(a => ValidateStringEmpty(a)).WithMessage("Contact Age should not be empty.");  
    13.             RuleFor(c => c.Gender).Must(g => ValidateStringEmpty(g)).WithMessage("Contact Gender should not be empty.");  
    14.             RuleFor(c => c.DOB).Must(d => ValidateStringEmpty(d.ToString())).WithMessage("Contact DOB should not be empty.");  
    15.             RuleFor(c => c.Address).Must(a => ValidateStringEmpty(a)).WithMessage("Contact Adress should not be empty.");  
    16.         }    
    17.   
    18.         bool ValidateStringEmpty(string stringValue){  
    19.             if (!string.IsNullOrEmpty(stringValue))  
    20.                 return true;  
    21.             return false;  
    22.         }  
    23.     }   
    24. }  
    6. How to register interfaces with Fresh IOC?
    We don’t need to include our own IOC container, FreshMvvm comes with a IOC container built in. It’s using TinyIOC underneath, but with different naming to avoid conflicts. 
    For example to Register IContactRepository, IValidator interfaces
    1. //Interface rgistration with FreshIOC  
    2. FreshIOC.Container.Register<IContactRepository, ContactRepository>();  
    3. FreshIOC.Container.Register<IValidator, ContactValidator>();  
    We have to set above code in App.xaml.cs from PCL project like below:
    1. using FluentValidation;  
    2. using FreshMvvm;  
    3. using FreshMvvmSample.PageModels;  
    4. using FreshMvvmSample.Services;  
    5. using FreshMvvmSample.Validator;  
    6. using Xamarin.Forms;  
    7.   
    8. namespace FreshMvvmSample  
    9. {  
    10.     public partial class App : Application  
    11.     {  
    12.         public App()  
    13.         {  
    14.             InitializeComponent();  
    15.   
    16.             //Interface rgistration with FreshIOC  
    17.             FreshIOC.Container.Register<IContactRepository, ContactRepository>();  
    18.             FreshIOC.Container.Register<IValidator, ContactValidator>();  
    19.   
    20.             // The root page of your application  
    21.             var mainPage = FreshPageModelResolver.ResolvePageModel<AddContactPageModel>();  
    22.             MainPage = new FreshNavigationContainer(mainPage);  
    23.         }  
    24.   
    25.         protected override void OnStart()  
    26.         {  
    27.             // Handle when your app starts  
    28.         }  
    29.   
    30.         protected override void OnSleep()  
    31.         {  
    32.             // Handle when your app sleeps  
    33.         }  
    34.   
    35.         protected override void OnResume()  
    36.         {  
    37.             // Handle when your app resumes  
    38.         }  
    39.     }  
    40. }  
    7. How to create PageModels with FreshMVVM in Xamarin.Forms?
    It is best practices to write business logic in view models before start to build pages user interface. In earlier I was already mentioned FreshMVVM will have PageModels and are not naming with ViewModels. So we are adding functionality for the page models below.
    • AddContactPageModel: Saving new contact details in database. 
    • ContactListPageModel: Read all contacts from database.
    • ContactDetailsPageModel: Read specific contact from database and delete/update same contact.
    Let's start write business logic to page models
    AddContactPageModel
    Above UI screen is for AddContactPage. So PageModel should have below properties and commands.
    Properties: Name, Mobile Number, Age, Gender, DOB, Address. And these properties will be the same for ContactDetailsPageModel. So we will add these properties into common page model name is BaseContactPageModel.
    1. using System;  
    2. using System.Collections.Generic;  
    3. using System.ComponentModel;  
    4. using System.Runtime.CompilerServices;  
    5. using FluentValidation;  
    6. using FreshMvvm;  
    7. using FreshMvvmSample.Models;  
    8. using FreshMvvmSample.Services;  
    9. using Xamarin.Forms;  
    10.   
    11. namespace FreshMvvmSample.PageModels  
    12. {  
    13.     public class BaseContactPageModel : FreshBasePageModel {  
    14.   
    15.         public ContactInfo _contact;  
    16.   
    17.         public IValidator _contactValidator;  
    18.         public IContactRepository _contactRepository;  
    19.   
    20.         public BaseContactPageModel(IContactRepository contactRepository, IValidator contactValidator){  
    21.             _contactRepository = contactRepository;  
    22.             _contactValidator = contactValidator;  
    23.         }  
    24.   
    25.         public string Name    
    26.         {    
    27.             get => _contact.Name;   
    28.             set{  
    29.                 _contact.Name = value;  
    30.                 RaisePropertyChanged("Name");  
    31.             }  
    32.         }     
    33.   
    34.         public string MobileNumber    
    35.         {  
    36.             get => _contact.MobileNumber;   
    37.             set {   
    38.                 _contact.MobileNumber = value;   
    39.                 RaisePropertyChanged("MobileNumber");  
    40.             }  
    41.         }    
    42.   
    43.         public string Age    
    44.         {  
    45.             get => _contact.Age;   
    46.             set {   
    47.                 _contact.Age = value;   
    48.                 RaisePropertyChanged("Age");  
    49.             }  
    50.         }   
    51.   
    52.         public string Gender    
    53.         {  
    54.             get => _contact.Gender;   
    55.             set {   
    56.                 _contact.Gender = value;   
    57.                 RaisePropertyChanged("Gender");  
    58.             }  
    59.         }   
    60.   
    61.         public DateTime DOB    
    62.         {  
    63.             get => _contact.DOB;   
    64.             set {  
    65.                 _contact.DOB = value;   
    66.                 RaisePropertyChanged("DOB");  
    67.             }  
    68.         }   
    69.   
    70.         public string Address    
    71.         {  
    72.             get => _contact.Address;   
    73.             set {   
    74.                 _contact.Address = value;   
    75.                 RaisePropertyChanged("Address");  
    76.             }  
    77.         }  
    78.   
    79.         List<ContactInfo> _contactList;  
    80.         public List<ContactInfo> ContactList  
    81.         {  
    82.             get => _contactList;  
    83.             set  
    84.             {  
    85.                 _contactList = value;  
    86.                 RaisePropertyChanged("ContactList");  
    87.             }  
    88.         }  
    89.     }  
    90. }  
    In above BaseContactPageModel, we also added below common interfaces
    • IValidator: To validate contact object.
    • IContactRepository: To access ContactInfo Table operations.
    Commands: 
    • AddContactCommand(for Save Contact Button click)
    • ViewAllContactsCommand (View All Contacts Label tap). 
    So create PageModels folder in PCL project and add below AddContactPageModel class.
    1. using System.Threading.Tasks;  
    2. using System.Windows.Input;  
    3. using FreshMvvmSample.Helpers;  
    4. using FreshMvvmSample.Models;  
    5. using FreshMvvmSample.Validator;  
    6. using FreshMvvmSample.Pages;  
    7. using Xamarin.Forms;  
    8. using FreshMvvmSample.Services;  
    9. using FluentValidation;  
    10.   
    11. namespace FreshMvvmSample.PageModels {  
    12.     public class AddContactPageModel : BaseContactPageModel {  
    13.   
    14.         public ICommand AddContactCommand { getprivate set; }  
    15.         public ICommand ViewAllContactsCommand { getprivate set; }  
    16.   
    17.         public AddContactPageModel(IContactRepository contactRepository, IValidator contactValidator): base(contactRepository, contactValidator){  
    18.             _contact = new ContactInfo();  
    19.   
    20.             AddContactCommand = new Command(async () => await AddContact());   
    21.             ViewAllContactsCommand = new Command(async () => await ShowContactList());   
    22.         }  
    23.   
    24.         async Task AddContact() {  
    25.             var validationResults = _contactValidator.Validate(_contact);      
    26.       
    27.             if (validationResults.IsValid){  
    28.                 bool isUserAccept = await CoreMethods.DisplayAlert("Add Contact""Do you want to save Contact details?""OK""Cancel");  
    29.                 if (isUserAccept) {  
    30.                     _contactRepository.InsertContact(_contact);  
    31.                     await CoreMethods.PushPageModel<ContactListPageModel>();  
    32.                 }  
    33.             }      
    34.             else {      
    35.                 await CoreMethods.DisplayAlert("Add Contact", validationResults.Errors[0].ErrorMessage, "Ok");      
    36.             }       
    37.         }  
    38.   
    39.         async Task ShowContactList(){   
    40.             await CoreMethods.PushPageModel<ContactListPageModel>();  
    41.         }  
    42.   
    43.         public bool IsViewAll => _contactRepository.GetAllContactsData().Count > 0 ? true : false;  
    44.     }  
    45. }  
    In AddContact method, we are validating ContactInfo object with help of ContactValidator before insert new contact to database. Also we are using Fresh MVVM CoreMethods to navigate to page models and displaying alert.
    ContactListPageModel
    Above UI screen is for ContactListPage. So PageModel should have below properties and commands.
    Properties: ContactList, SelectedContactItem
    CommandsAddCommand, DeleteAllContactsCommand
    In PCL project PageModels folder, Add below ContactListPageModel class.
    1. using System;  
    2. using System.Threading.Tasks;  
    3. using System.Windows.Input;  
    4. using FluentValidation;  
    5. using FreshMvvmSample.Models;  
    6. using FreshMvvmSample.Pages;  
    7. using FreshMvvmSample.Services;  
    8. using Xamarin.Forms;  
    9.   
    10. namespace FreshMvvmSample.PageModels  
    11. {  
    12.     public class ContactListPageModel: BaseContactPageModel {  
    13.   
    14.         public ICommand AddCommand { getprivate set; }  
    15.         public ICommand DeleteAllContactsCommand { getprivate set; }  
    16.   
    17.         public ContactListPageModel(IContactRepository contactRepository, IValidator contactValidator) : base(contactRepository, contactValidator) {  
    18.              
    19.             AddCommand = new Command(async () => await ShowAddContact());   
    20.             DeleteAllContactsCommand = new Command(async () => await DeleteAllContacts());  
    21.         }  
    22.   
    23.         protected override void ViewIsAppearing(object sender, EventArgs e){  
    24.             base.ViewIsAppearing(sender, e);  
    25.   
    26.             FetchContacts();  
    27.         }  
    28.   
    29.         void FetchContacts(){  
    30.             ContactList = _contactRepository.GetAllContactsData();  
    31.         }  
    32.   
    33.         async Task ShowAddContact() {  
    34.             await CoreMethods.PushPageModel<AddContactPageModel>();  
    35.         }  
    36.   
    37.         async Task DeleteAllContacts(){  
    38.             bool isUserAccept = await CoreMethods.DisplayAlert("Contact List""Delete All Contacts Details ?""OK""Cancel");  
    39.             if (isUserAccept){  
    40.                 _contactRepository.DeleteAllContacts();  
    41.                 await CoreMethods.PushPageModel<AddContactPageModel>();  
    42.             }  
    43.         }  
    44.   
    45.         async void ShowContactDetails(int selectedContactID){  
    46.             await CoreMethods.PushPageModel<ContactDetailsPageModel>(selectedContactID);  
    47.         }  
    48.   
    49.         ContactInfo _selectedContactItem;  
    50.         public ContactInfo SelectedContactItem {  
    51.             get => _selectedContactItem;  
    52.             set {  
    53.                 if (value != null){  
    54.                     _selectedContactItem = value;  
    55.                     RaisePropertyChanged("SelectedContactItem");  
    56.                     ShowContactDetails(value.Id);  
    57.                 }  
    58.             }  
    59.         }  
    60.     }  
    61. }  
    DetailsPageModel
    Above UI screen is for ContactDetailsPage. So ViewModel should have below properties and commands.
    Properties: All properties of BaseContactPageModel as it is very similar to AddContactPageModel.
    CommandsUpdateContactCommand, DeleteContactCommand
    In PCL project PageModels folder, Add below ContactDetailsPageModel class.
    1. using System.Threading.Tasks;  
    2. using System.Windows.Input;  
    3. using FluentValidation;  
    4. using FreshMvvmSample.Models;  
    5. using FreshMvvmSample.Services;  
    6. using Xamarin.Forms;  
    7.   
    8. namespace FreshMvvmSample.PageModels  
    9. {  
    10.     public class ContactDetailsPageModel: BaseContactPageModel {  
    11.   
    12.         public ICommand UpdateContactCommand { getprivate set; }  
    13.         public ICommand DeleteContactCommand { getprivate set; }  
    14.   
    15.         public ContactDetailsPageModel(IContactRepository contactRepository, IValidator contactValidator) : base(contactRepository, contactValidator) {  
    16.             _contact = new ContactInfo();  
    17.   
    18.             UpdateContactCommand = new Command(async () => await UpdateContact());  
    19.         }  
    20.   
    21.         public override void Init(object initData){  
    22.             _contact.Id = (int)initData;  
    23.   
    24.             FetchContactDetails();  
    25.         }  
    26.   
    27.         void FetchContactDetails(){  
    28.             _contact = _contactRepository.GetContactData(_contact.Id);  
    29.         }  
    30.   
    31.         async Task UpdateContact() {  
    32.             var validationResults = _contactValidator.Validate(_contact);  
    33.   
    34.             if (validationResults.IsValid) {  
    35.                 bool isUserAccept = await CoreMethods.DisplayAlert("Contact Details""Update Contact Details""OK""Cancel");  
    36.                 if (isUserAccept) {  
    37.                     _contactRepository.UpdateContact(_contact);  
    38.                     await CoreMethods.PopPageModel();  
    39.                 }  
    40.             }  
    41.             else {  
    42.                 await CoreMethods.DisplayAlert("Add Contact", validationResults.Errors[0].ErrorMessage, "Ok");  
    43.             }  
    44.         }  
    45.   
    46.         async Task DeleteContact() {  
    47.             bool isUserAccept = await CoreMethods.DisplayAlert("Contact Details""Delete Contact Details""OK""Cancel");  
    48.             if (isUserAccept) {  
    49.                 _contactRepository.DeleteContact(_contact.Id);  
    50.                 await CoreMethods.PopPageModel();  
    51.             }  
    52.         }  
    53.     }  
    54. }  
    8. How to create Pages and bind with PageModels in FreshMVVM?
    We completed the business logic in all above page models and now we can create UI in Pages folder and no need to bind it to the view models as I already mentioned FreshMVVM having power of BindingContext on the page will be automatically set with the page model.
    Add Contact
    We need to create a page that can provide UI to insert new contact details. If we observe the above UI android screens, AddContact and Contacts Details UI is almost similar. So we can build common UI with help of ContentView and then reuse it in AddContact and Contact Details Pages.
    So create Pages folder in PCL and add below ContentView. Make sure UI elements should bind to relevant view model properties (Name, Mobile Number, Age, Gender, DOB, Address).
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="FreshMvvmSample.Pages.ContactCommonView">  
    3.     <StackLayout Spacing="12">  
    4.         <Entry x:Name="txtContactName" Text="{Binding Name}" HeightRequest="40" BackgroundColor="White" Placeholder="Contact Name" HorizontalOptions="FillAndExpand"/>  
    5.         <Entry  x:Name="txtMobileNumber" Keyboard="Telephone" Text="{Binding MobileNumber}" BackgroundColor="White" HeightRequest="40" Placeholder="Mobile Number" HorizontalOptions="FillAndExpand"/>  
    6.         <StackLayout Orientation="Horizontal">  
    7.           <Entry x:Name="txtAge" Text="{Binding Age}" HeightRequest="40" BackgroundColor="White" Placeholder="Age" HorizontalOptions="FillAndExpand"/>  
    8.           <Picker x:Name="GenderPicker" SelectedItem="{Binding Gender}" Title="Gender" BackgroundColor="White" HeightRequest="40" HorizontalOptions="FillAndExpand">  
    9.                 <Picker.ItemsSource>  
    10.                     <x:Array Type="{x:Type x:String}">  
    11.                         <x:String>Male</x:String>  
    12.                         <x:String>FeMale</x:String>  
    13.                     </x:Array>  
    14.                 </Picker.ItemsSource>  
    15.             </Picker>  
    16.         </StackLayout>  
    17.           <DatePicker x:Name="txtDOB" Date="{Binding DOB}" BackgroundColor="White" HeightRequest="40" HorizontalOptions="FillAndExpand"/>  
    18.          <Entry x:Name="txtAddress" Text="{Binding Address}" BackgroundColor="White"  HeightRequest="40" Placeholder="Address"  HorizontalOptions="FillAndExpand"/>  
    19.     </StackLayout>  
    20. </ContentView>  
    Declare above ContentView name space in Xaml to reuse it in AddContact.
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:FreshMvvmSample.Pages">  
    3.     <StackLayout Padding="20" Spacing="12">  
    4.         <local:ContactCommonView />  
    5.     </StackLayout>  
    6. </ContentPage>  
    Now in Pages folder create AddContactPage.xaml page and add below xaml code
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"   
    3.              xmlns:local="clr-namespace:FreshMvvmSample.Pages" x:Class="FreshMvvmSample.Pages.AddContactPage">  
    4.     <StackLayout Padding="20" Spacing="12">  
    5.         <local:ContactCommonView />  
    6.         <Button x:Name="SubmitButton" Command="{Binding AddContactCommand}" BorderRadius="0" Text="Save Contact" FontAttributes="Bold" TextColor="White" BackgroundColor="#5989B5"/>  
    7.         <Label Text="View All Contacts" IsVisible="{Binding IsViewAll}" x:Name="ViewLbl" TextColor="Black" HorizontalOptions="EndAndExpand" FontSize="15">    
    8.         <Label.GestureRecognizers>    
    9.         <TapGestureRecognizer Command="{Binding ViewAllContactsCommand}" NumberOfTapsRequired="1" />    
    10.         </Label.GestureRecognizers>    
    11.         </Label>    
    12.     </StackLayout>  
    13. </ContentPage>  
    Contact List
    We need to create a page that can display all contacts details, also to add new contact details and delete all contacts.
    In Pages folder, create ContactListPage.xaml and add below code.
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="FreshMvvmSample.Pages.ContactListPage">  
    3.    <Grid Padding="10,20,10,40">    
    4.         <Grid.RowDefinitions>    
    5.             <RowDefinition Height="Auto" />    
    6.             <RowDefinition Height="*" />    
    7.             <RowDefinition Height="Auto" />    
    8.         </Grid.RowDefinitions>    
    9.         <Grid Grid.Row="0">    
    10.         <Grid.ColumnDefinitions>    
    11.         <ColumnDefinition Width="*" />    
    12.         <ColumnDefinition Width="*" />    
    13.         </Grid.ColumnDefinitions>   
    14.         <Button Text="New Contact" Grid.Row="0" Grid.Column="1" FontAttributes="Bold" BorderRadius="0" HeightRequest="40" BorderColor="Black" BackgroundColor="Transparent" BorderWidth="1"  TextColor="Black"  Command="{Binding AddCommand}" />    
    15.         </Grid>    
    16.         <ListView x:Name="ContactListView" HasUnevenRows="true" Grid.Row="1" SeparatorColor="Black" ItemsSource="{Binding ContactList}"  
    17.          SelectedItem="{Binding SelectedContactItem, Mode=TwoWay}">    
    18.             <ListView.ItemTemplate>    
    19.                 <DataTemplate>    
    20.                     <ViewCell>    
    21.                             <Grid  Padding="10">    
    22.                                 <Grid.RowDefinitions>    
    23.                                     <RowDefinition Height="Auto" />    
    24.                                     <RowDefinition Height="Auto" />    
    25.                                 </Grid.RowDefinitions>    
    26.                                 <Grid.ColumnDefinitions>    
    27.                                     <ColumnDefinition Width="Auto" />    
    28.                                     <ColumnDefinition Width="*" />    
    29.                                 </Grid.ColumnDefinitions>    
    30.                                 <Label Text="{Binding Name}" Grid.Row="0" Font="20" TextColor="Black" />   
    31.                                 <Label Text="{Binding MobileNumber}" Grid.Row="0" Font="20" Grid.Column="1" HorizontalOptions="EndAndExpand" HorizontalTextAlignment="End" TextColor="Black" />    
    32.                                 <Label Text="{Binding Address}" Grid.Row="1" Grid.Column="0" HorizontalOptions="FillAndExpand" TextColor="Black" />    
    33.                         </Grid>    
    34.                     </ViewCell>    
    35.                 </DataTemplate>    
    36.             </ListView.ItemTemplate>    
    37.         </ListView>   
    38.         <Button Text="Delete All Contacts" Grid.Row="2" BorderRadius="0" VerticalOptions="EndAndExpand" FontAttributes="Bold" TextColor="White" BackgroundColor="#5989B5" Command="{Binding DeleteAllContactsCommand}" />    
    39.     </Grid>    
    40. </ContentPage>  
    In Above xaml code we added
    • Two buttons (New Contact, Delete All Contacts)
    • ListView (To display contacts list and to set ItemsSource ContactList)  
    DetailsPage:
    We need to create a page that can display particular contact details, also to update/delete contact details.
    In Pages folder, create ContactDetailsPage.xaml and add below code.
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"   
    3.              xmlns:local="clr-namespace:FreshMvvmSample.Pages" x:Class="FreshMvvmSample.Pages.ContactDetailsPage">  
    4.      <StackLayout Padding="20" Spacing="12">  
    5.         <local:ContactCommonView />  
    6.          <Button Text="Update" BorderRadius="0" Margin="0,30,0,0" FontAttributes="Bold" TextColor="White" BackgroundColor="#5989B5" Command="{Binding UpdateContactCommand}" />    
    7.         <Button Text="Delete" BorderRadius="0" Margin="0,30,0,0" FontAttributes="Bold" TextColor="White" BackgroundColor="#5989B5" Command="{Binding DeleteContactCommand}" />    
    8.     </StackLayout>  
    9. </ContentPage>  
    9. How to use FreshMvvm built-in navigation class to define the start page for the application?
    It is crucial point to set the starting page, and fortunately FreshMVVM having FreshPageModelResolver to set MainPage for the application.
    So open App.xaml.cs from PCL project and then add below code to set AddContactPage as a start page for the application.




  • using FreshMvvm;  
  • using FreshMvvmSample.PageModels;  
  • using Xamarin.Forms;  
  •   
  • namespace FreshMvvmSample  
  • {  
  •     public partial class App : Application  
  •     {  
  •         public App()  
  •         {  
  •             InitializeComponent();  
  •   
  •             // The root page of your application  
  •             var mainPage = FreshPageModelResolver.ResolvePageModel<AddContactPageModel>();  
  •             MainPage = new FreshNavigationContainer(mainPage); 
  •         }  
  •   
  •         protected override void OnStart()  
  •         {  
  •             // Handle when your app starts  
  •         }  
  •   
  •         protected override void OnSleep()  
  •         {  
  •             // Handle when your app sleeps  
  •         }  
  •   
  •         protected override void OnResume()  
  •         {  
  •             // Handle when your app resumes  
  •         }  
  •     }  
  • }  
  • Demo screens from iOS:
    You can directly work on below sample source code to understand the this article. 

    FreshMvvmSample

    FeedBack Note: Please share your thoughts, what you think about this post, Is this post really helpful for you? I always welcome if you drop comments on this post and it would be impressive.

    Follow me always at @Subramanyam_B
    Have a nice day by  :)

    1 comment:

    1. Have you considered updating the article from SQLite.Net-PCL to SQLite-net-pcl (yes, there is apparently a difference)? I noticed problems with Android 7+ when using SQLite.Net-PCL, and the author on Github hasn't updated it yet. Also SQLite-net-pcl has async methods which are supposed to be much more reliable when using a SQLite db.

      ReplyDelete

    Search Engine Submission - AddMe