Introduction
This article demonstrates how to create a login page in Xamarin.Forms using MVVM concepts. We will use VS 2017 Community Edition update 15.4 version and 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.
Next, select a blank app, Xamarin.Forms, and Portable Class Library (PCL) options/ Then, click OK.
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.
- using System;
- using System.ComponentModel;
- using System.Windows.Input;
- using Xamarin.Forms;
- namespace XF_Login.ViewModels
- {
- public class LoginViewModel : INotifyPropertyChanged
- {
- public Action DisplayInvalidLoginPrompt;
- public event PropertyChangedEventHandler PropertyChanged = delegate { };
- private string email;
- public string Email
- {
- get { return email; }
- set
- {
- email = value;
- PropertyChanged(this, new PropertyChangedEventArgs("Email"));
- }
- }
- private string password;
- public string Password
- {
- get { return password; }
- set
- {
- password= value;
- PropertyChanged(this, new PropertyChangedEventArgs("Password"));
- }
- }
- public ICommand SubmitCommand { protected set; get; }
- public LoginViewModel()
- {
- SubmitCommand = new Command(OnSubmit);
- }
- public void OnSubmit()
- {
- if (email != "[email protected]" || password != "secret")
- {
- DisplayInvalidLoginPrompt();
- }
- }
- }
- }
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 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 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.
- <?xml version="1.0" encoding="utf-8" ?>
- <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
- x:Class="XF_Login.Pages.LoginPage"
- BackgroundImage="logo.jpg">
- <ContentPage.Content>
- <StackLayout Orientation="Vertical" Padding="30" Spacing="40">
- <BoxView HeightRequest="10"/>
- <Image HorizontalOptions="Center" WidthRequest="300" Source="maco.jpg"/>
- <Frame BackgroundColor="#BF043055" HasShadow="False">
- <StackLayout Orientation="Vertical" Spacing="10">
- <Entry x:Name="Email" Text="{Binding Email}" Placeholder="Email"
- PlaceholderColor="White" HeightRequest="40"
- Keyboard="Email"
- TextColor="White"/>
- <Entry x:Name="Password" Text="{Binding Password}" Placeholder="Senha"
- PlaceholderColor="White" HeightRequest="40"
- IsPassword="True"
- TextColor="White"/>
- </StackLayout>
- </Frame>
- <Button Command="{Binding SubmitCommand}" Text="Login" TextColor="White"
- FontAttributes="Bold" FontSize="Large" HorizontalOptions="FillAndExpand"
- BackgroundColor="#088da5" />
- </StackLayout>
- </ContentPage.Content>
- </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,
- <Entry x: Name = "Email" Text = "{Binding Email}" Placeholder = "Email"
- PlaceholderColor = "White" HeightRequest = "40"
- Keyboard = "Email"
- TextColor = "White" />
- the field to enter the Password using the View Entry,
- <Entry x: Name = "Password" Text = "{Binding Password}" Placeholder = "Password"
- PlaceholderColor = "White" HeightRequest = "40"
- IsPassword = "True"
- TextColor = "White" />
- the command button.
- <"Button Command =" {Binding SubmitCommand} "Text =" Login "TextColor =" White "
- FontAttributes = "Bold" FontSize = "Large" HorizontalOptions = "FillAndExpand"
- 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.
- using System;
- using Xamarin.Forms;
- using Xamarin.Forms.Xaml;
- using XF_Login.ViewModels;
-
- namespace XF_Login.Pages
- {
- [XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class LoginPage : ContentPage
- {
- public LoginPage()
- {
- var vm = new LoginViewModel();
- this.BindingContext = vm;
- vm.DisplayInvalidLoginPrompt += () => DisplayAlert("Error", "Invalid Login, try again", "OK");
- InitializeComponent();
-
- Email.Completed += (object sender, EventArgs e) =>
- {
- Password.Focus();
- };
-
- Password.Completed += (object sender, EventArgs e) =>
- {
- vm.SubmitCommand.Execute(null);
- };
- }
- }
- }
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 Android project:
Now, just change the App.xaml.cs file to display the Login page.
- using Xamarin.Forms;
- namespace XF_Login
- {
- public partial class App : Application
- {
- public App()
- {
- InitializeComponent();
- MainPage = new XF_Login.Pages.LoginPage();
- }
-
- protected override void OnStart() {
-
- }
- protected override void OnSleep() {
-
- }
- protected override void OnResume() {
-
- }
- }
- }
Running the project, we will get the following result in the Genymotion Emulator for Android.
Summary
This was the process of creating a Xamarin Login Page using MVVM concepts with Visual Studio 2017 and C# language.