Xamarin.Forms - Create A Login Page (MVVM)

Introduction

 
This article demonstrates how to create a login page in Xamarin.Forms using MVVM concepts. We will use the VS 2017 Community Edition update 15.4 version and the C# language.
 
Implementation
 
We are going to code in the following steps.
  • Create the ViewModels and Pages Folder in Project;
  • Create the LoginViewModel class;
  • Create the LoginPage view;
  • Set binding to LoginViewModel in code-behind;
  • Copy images files in Android’s Project directory Resource/drawable
So, let’s get started.
 
Step 1
 
Open Visual Studio 2017 Community Edition.
 
Click on Create New Project -> Installed -> Visual C# -> Cross-Platforms -> Cross-Platform App (Xamarin) and give project name XF_Login and project location.
 
Xamarin
 
Next, select a blank app,  Xamarin.Forms, and Portable Class Library (PCL) options/ Then, click OK.
 
Xamarin
 
Step 2
 
Let's create two new folders in our project.
  • The ViewModels folder where we will create the LoginViewModel class
  • The Pages folder where we will create the Login page: LoginPage.xaml
Go to Solution Explorer -> Project Name (Portable), then right-click to Add -> New Folder. It opens a new dialog box; give the name ViewModels.
 
Repeat the operation and create the Pages folder in the project.
 
Step 3
 
Right-click the ViewModels folder and select  Add ->Class. This opens a new dialog box. Give a name to LoginViewModel.cs
 
Open LoginViewModel.cs file and give the following code.
  1. using System;  
  2. using System.ComponentModel;  
  3. using System.Windows.Input;  
  4. using Xamarin.Forms;  
  5. namespace XF_Login.ViewModels  
  6. {  
  7.     public class LoginViewModel : INotifyPropertyChanged  
  8.     {  
  9.         public Action DisplayInvalidLoginPrompt;   
  10.         public event PropertyChangedEventHandler PropertyChanged = delegate { };  
  11.         private string email;  
  12.         public string Email
  13.         {  
  14.             get { return email; }  
  15.             set  
  16.             {  
  17.                 email = value;  
  18.                 PropertyChanged(thisnew PropertyChangedEventArgs("Email"));  
  19.             }  
  20.         }  
  21.         private string password;    
  22.         public string Password
  23.         {  
  24.             get { return password; }  
  25.             set  
  26.             {  
  27.                 password= value;  
  28.                 PropertyChanged(thisnew PropertyChangedEventArgs("Password"));  
  29.             }  
  30.         }  
  31.         public ICommand SubmitCommand protected set; get; }  
  32.         public LoginViewModel()  
  33.         {  
  34.             SubmitCommand = new Command(OnSubmit);  
  35.         }  
  36.         public void OnSubmit()  
  37.         {  
  38.             if (email != "macoratti@yahoo.com" || password != "secret")  
  39.             {  
  40.                 DisplayInvalidLoginPrompt();  
  41.             }  
  42.         }  
  43.     }  
  44. }  
In this code, we created the following properties: Email, Password, and the command SubmitCommand() that we will use in the Login command button on the Login page. We will use the ICommand interface that allows defining and implementing a command of what we call commanding.
 
I am not using a database to validate the Email and Password; for simplicity, I'm doing a very simple code validation.
 
The LoginViewModel class implements the INotifyPropertyChanged interface so that the changes made to properties are notified to Views.
 
We also defined the DisplayInvalidLoginPrompt method using an Action delegate where this method will only display a message returning no value.
 
Now, we can define our View of LoginPage in the Pages folder.
 
Step 4
 
Select the Pages folder and on the Project menu, click "Add New Item" and select the Content Page template by entering the name LoginPage.xaml.
 
Then, give the following code.
  1. <?xml version="1.0" encoding="utf-8" ?>  
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"  
  4.              x:Class="XF_Login.Pages.LoginPage"  
  5.              BackgroundImage="logo.jpg">  
  6.     <ContentPage.Content>  
  7.         <StackLayout Orientation="Vertical" Padding="30" Spacing="40">  
  8.             <BoxView HeightRequest="10"/>  
  9.             <Image HorizontalOptions="Center" WidthRequest="300" Source="maco.jpg"/>  
  10.             <Frame BackgroundColor="#BF043055" HasShadow="False">  
  11.                 <StackLayout Orientation="Vertical" Spacing="10">  
  12.                     <Entry x:Name="Email" Text="{Binding Email}" Placeholder="Email"   
  13.                            PlaceholderColor="White" HeightRequest="40"   
  14.                            Keyboard="Email"  
  15.                            TextColor="White"/>  
  16.                     <Entry x:Name="Password" Text="{Binding Password}" Placeholder="Senha"   
  17.                            PlaceholderColor="White" HeightRequest="40"   
  18.                            IsPassword="True"  
  19.                            TextColor="White"/>  
  20.                 </StackLayout>  
  21.             </Frame>  
  22.             <Button Command="{Binding SubmitCommand}" Text="Login" TextColor="White"  
  23.                     FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand"  
  24.                     BackgroundColor="#088da5" />  
  25.         </StackLayout>  
  26.     </ContentPage.Content>  
  27. </ContentPage>  
In the file MainPage.xaml.cs, we have the following code where we define 
- the background image of the page :  BackgroundImage = "logo.jpg"
- the centered image above the Frame:  <Image HorizontalOptions = "Center" WidhRequest = "300" Source = "maco.jpg" />
- the field to inform the Email using the View Entry,
  1. <Entry x: Name = "Email" Text = "{Binding Email}" Placeholder = "Email"  
  2.                          PlaceholderColor = "White" HeightRequest = "40"  
  3.                          Keyboard = "Email"  
  4.                          TextColor = "White" />  
- the field to enter the Password using the View Entry,
  1. <Entry x: Name = "Password" Text = "{Binding Password}" Placeholder = "Password"  
  2.                            PlaceholderColor = "White" HeightRequest = "40"  
  3.                            IsPassword = "True"  
  4.                            TextColor = "White" />  
- the command button.
  1. <"Button Command =" {Binding SubmitCommand} "Text =" Login "TextColor =" White "  
  2.  FontAttributes = "Bold" FontSize = "Large" HorizontalOptions = "FillAndExpand"  
  3.  BackgroundColor = "# 088da5" /> 
We are using databinding to bind the value of the Views used with the Email, Password, and SubmitCommand properties defined in LoginViewModel.
 
But how our View will communicate to ViewModel?
 
We do this in the code-behind file LoginPage.xaml.cs by setting the following code.
  1. using System;  
  2. using Xamarin.Forms;  
  3. using Xamarin.Forms.Xaml;  
  4. using XF_Login.ViewModels;  
  5.   
  6. namespace XF_Login.Pages  
  7. {  
  8.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  9.     public partial class LoginPage : ContentPage  
  10.     {  
  11.         public LoginPage()  
  12.         {  
  13.             var vm = new LoginViewModel();  
  14.             this.BindingContext = vm;  
  15.             vm.DisplayInvalidLoginPrompt += () => DisplayAlert("Error""Invalid Login, try again""OK");  
  16.             InitializeComponent();  
  17.   
  18.             Email.Completed += (object sender, EventArgs e) =>  
  19.             {  
  20.                 Password.Focus();  
  21.             };  
  22.   
  23.             Password.Completed += (object sender, EventArgs e) =>  
  24.             {  
  25.                 vm.SubmitCommand.Execute(null);  
  26.             };  
  27.         }  
  28.     }  
  29. }  
In this code, we are creating an instance of LoginViewModel and doing the binding with our View using the BindingContext property.
 
We have also implemented the DisplayInvalidLoginPrompt() method to display an error message.
 
Finally, we are treating the Completed Views Entry event that occurs when the user ends the text in the View Entry for Email and Password with the Return key, to get better user experience.
 
Preparing the images used in the project
 
The images used in the project must be prepared to be displayed on each platform.  The image logo.jpg and maco.jpg, used in the Project have the appropriate name and size to be displayed in the Android project which is where I'm testing the project.
 
We are copying the images to the folder Resources/drawable in the Android project:
 
Xamarin
 
Now, just change the App.xaml.cs file to display the Login page.
  1. using Xamarin.Forms;  
  2. namespace XF_Login  
  3. {  
  4.     public partial class App : Application  
  5.     {  
  6.         public App()  
  7.         {  
  8.             InitializeComponent();  
  9.             MainPage = new XF_Login.Pages.LoginPage();  
  10.         }  
  11.   
  12.         protected override void OnStart() {  
  13.             // Handle when your app starts  
  14.         }  
  15.         protected override void OnSleep() {  
  16.             // Handle when your app sleeps  
  17.         }  
  18.         protected override void OnResume() {  
  19.             // Handle when your app resumes  
  20.         }  
  21.     }  
  22. }  
Running the project, we will get the following result in the Genymotion Emulator for Android.
 
Xamarin
  
Xamarin
 

Summary

 
This was the process of creating a Xamarin Login Page using MVVM concepts with Visual Studio 2017 and C# language.