Xamarin.Forms is a cross-platform UI toolkit that allows developers to efficiently create native user interface layouts that can be shared across iOS, Android, and Universal Windows Platform apps. This series introduces the basics of Xamarin.Forms development and covers building multi-platform and multi-screen applications.
- Installation of Visual Studio 2017 for Windows with Xamarin [instructions]
- Installation of GitHub Desktop Client [instructions] (You can use whatever client you are familiar with.)
- Update Visual Studio 2017 for Windows [instructions]
- Installation of Visual Studio for Mac [instructions]
- Installation of GitHub Desktop Client [instructions]
- Update Visual Studio for Mac [instructions]
Documentation: [here]
Create new Solution with Xamarin Forms Template
- Open Visual Studio
- Open Menu
File > New > Projects - Select Template
Installed > Visual C# > Cross-Platform > Mobile App (Xamarin.Forms)
- Enter the name for project your project (i.e.
NorthDallas.Contacts) - Select the settings as shown in the picture and click
Ok
- Project will be generated with all the needed files
Setup LiveReload for rapid iterations through development.
- Open Menu
Tools > Extensions and Updates - Select
Onlinefrom the left - Type
Live Reloadin the search bar
- Click
Download - You will be prompted to restart Visual Studio. Do so.
- Click
Modifywhen prompted by Live Reload installer.
- Reopen Visual Studio after the installation is complete
- Re-Open your newly created project
- Right Click
Dependenciesin your Xamarin.Forms ProjectNorthDallas.Contacts - Click
Manage NuGet Packages - Click the
BrowseTab - Select
LiveReloadfor thePackage source
- Install the
Xamarin.LiveReloadpackage - Add
LiveReload.Init();to the class App in the Xamarin.Forms ProjectNorthDallas.Contacts
public partial class App : Application
{
public App ()
{
// Initialize Live Reload.
#if DEBUG
LiveReload.Init();
#endif
InitializeComponent();
MainPage = new MainPage();
}
}- Open
NorthDallas.Contacts\MainPage.xamlpage - Click the
Connectlink in the yellow bar above your XAML page
- Open your firewall for the Live Reload connection

- Select
NorthDallas.Contacts.Androidfrom your start project selector - Select your emulator and press run

- If you are using Live Reload, you may make changes to the
NorthDallas.Contacts\MainPage.xamlpage and save the file to see the changes.
- With your
MainPage.xamlpage open, change the label to say "Welcome to Dallas!" from "Welcome to Xamarin.Forms!" - If you are running LiveReload, it should just update in the emulator. Otherwise you have to run the app again.
We'll be using Model-View-ViewModel for Xamarin.Forms. There are a lot of advantages to them. The first thing we'll need to do is create a ViewModel.
- Stop the application from running.
- In the
NorthDallas.ContactsSolution, right click the project and selectManage NuGet Packages for Solutionfrom the context menu. - Select
nuget.orgas yourPackage Source - Click on the
Browsetab - Type the following into the search
Refractored.MvvmHelpers - In the right pane, select all the projects and click
Install - In the
NorthDallas.Contactsproject, right click the project and chooseAdd > New Folder. - Name as
ViewModels - Now right click that folder and select
Add > Class - Enter the name
ContactListViewModel.csand clickAdd - Make
ContactListViewModelimplementINotifyPropertyChangedusingMvvmHelpers
public class ContactListViewModel
: BaseViewModel
{
public ContactListViewModel()
{
Title = "Welcome to the Contact List";
}
}Views is another piece of the MVVM architecture. This is what the user interacts with, the UI.
- Create another folder inside of
NorthDallas.ContactsnamedViews. - Right click the new folder
Viewsand chooseAdd > New Itemfrom the context menu. - Select the template
Xamarin.Forms > Content Pageand enter the nameContactListView.xamland clickAdd.
- Point the application to start with
ContactListView.xaml - Open
NorthDallas.Contacts\App.xaml.csfile from under theApp.xamlfile.
- Assign a new instance of
ContactListViewto theMainPageproperty by replacing the existing assignment.
MainPage = new ContactListView();- You can delete
NorthDallas.Contacts\MainPage.xamlfile now. - Run the application and see that it now starts with the new view.
Most of Mobile development is displaying lists of data. Let's add a ListView to ContactListView page.
- Create a new property to store contacts in
ContactListViewModel.cs.
public ObservableRangeCollection<string> Contacts { get; set; } =
new ObservableRangeCollection<string>();- Add fake data to the
ContactListViewModelto render on the view by placing the following code in your constructor.
Contacts.AddRange(new string[]
{
"Sean",
"Homero",
"Gabrielle",
"Anna",
"Annette",
"Bella",
"Brett",
"Stephen"
});- Replace the
Labelin theNorthDallas.Contacts\Views\ContactListView.xamlwith aListView.
<ListView ItemsSource="{Binding Contacts}"
RowHeight="70">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding .}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>- Open
NorthDallas.Contacts\View\ContactListView.xaml.csfrom under theContactListView.xamlfile. - Add the
ContactListViewModelas theBindingContextin the constructorContactListViewclass.
public ContactListView ()
{
BindingContext = new ContactListViewModel();
InitializeComponent ();
}- Run the Application and see the list of people.
For this workshop, we will be using RandomUser API [documentation]. We will be using JSON 2 CSharp to generate POCO (Plain Old CSharp Object).
- Take a results example from the documentation page and paste it into the JSON 2 CSharp page.
- Click the
Generatebutton. - Click the
Copybutton at the bottom of the page, select the code, and copy the text to get the generated code. - Create a new folder
Modelsin theNorthDallas.Contactsproject. - Create new a class in the
Modelsfolder by right clicking the folder and choosingAdd > Class.... - Name the class
RandomUserResults.cs. - Replace the class in the new file with the copied code from JSON 2 CSharp.
- In the
NorthDallas.ContactsSolution, right click the project and selectManage NuGet Packages for Solutionfrom the context menu. - Select
nuget.orgas yourPackage Source - Click on the
Browsetab - Type the following into the search
Newtonsoft.Json - In the right pane, select all the projects and click
Install - Create a new folder
Servicesin theNorthDallas.Contactsproject. - Create new a class in the
Servicesfolder by right clicking the folder and choosingAdd > Class.... - Name the new class
UserService.cs. - Replace the new class with the following.
public class UserService
{
public async Task<List<Result>> GetUsersAsync(int count)
{
var httpClient = new HttpClient();
var response = await httpClient.GetAsync($"https://randomuser.me/api/?results={count}&seed=northdallas");
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
var results = JsonConvert.DeserializeObject<RootObject>(json);
return results.results;
}
throw new Exception("API call failed!");
}
}Now that you have created a client to pull user data from RandomUser.me, you need to use the data.
- Open
NorthDallas.Contacts\ViewModels\ContactListViewModel.csand add a new parameter to theContactListViewModelconstructor.
public ContactListViewModel(UserService userService)- Create a new class variable inside of the
ContactListViewModel.
private UserService _userService;- Assign the constructor parameter to the class variable inside the constructor and remove the
AddRangefrom the constructor.
public ContactListViewModel(UserService userService)
{
_userService = userService;
}- Update the
Contactsproperty to the type ofObservableRangeCollection<Result>.
public ObservableRangeCollection<Result> Contacts { get; set; } =
new ObservableRangeCollection<Result>();- Create a new method inside of
NorthDallas.Contacts\ViewModels\ContactListViewModel.csand name itExecuteRefreshCommandAsync.
private async Task ExecuteRefreshCommandAsync()
{
try
{
IsBusy = true;
Contacts.Clear();
Contacts.AddRange(await _userService.GetUsersAsync(100));
}
catch(Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}- Add a new command. We will use the
RefreshCommandto pull down random users from the API.
private ICommand _refreshCommand;
public ICommand RefreshCommand =>
_refreshCommand ?? (_refreshCommand = new Command(async () => await ExecuteRefreshCommandAsync()));- Open the
NorthDallas.Contacts\Views\ContactListView.xaml.csfile from under theContactListView.xamlfile. - Create a new class variable to store the view model.
private ContactListViewModel _viewModel;- Assign the new
ContactListViewModelto the_viewModelinside of the constructor ofContactListView.
BindingContext = _viewModel = new ContactListViewModel(new UserService());- Now we want to pull the data on when the page is first being put on the screen.
protected override void OnAppearing()
{
base.OnAppearing();
_viewModel.RefreshCommand.Execute(null);
}- Now run the application. You will find the cells blank.
- Fix this by updating your
TextCellto bind to name.
<TextCell Text="{Binding name.first}" Detail="{Binding name.last}" />- Run the application again.
While a list of names is great, you will want to display more than one or two pieces of data or even an email. You need a custom cell for this.
- You need to replace the
TextCellwith aViewCell - Your content for the template will be inside the
ViewCell - Replace your
TextCellwith the following.
<ViewCell>
<StackLayout>
<Label FontAttributes="Bold">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding name.last}" />
<Span Text=", " />
<Span Text="{Binding name.first}" />
</FormattedString>
</Label.FormattedText>
</Label>
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding location.city}" />
<Span Text=", " />
<Span Text="{Binding location.state}" />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ViewCell>- To add an image, you will need to include another NuGet package.
- Click on the
Browsetab - Type the following into the search
Xamarin.FFImageLoading.Forms - In the right pane, select all the projects and click
Install - In the
NorthDallas.ContactsSolution, right click the project and selectManage NuGet Packages for Solutionfrom the context menu. - In the right pane, select the iOS, Android and UWP projects and click
Install - Click on the
Updatestab - Check the box for
Xamarin.Forms - Click the
Updatebutton in the left pane - Accept the EULA
- Open the
NorthDallas.Contacts.Android\MainActivity.csfile and add the following to the beginning of theOnCreatemethod.
Xamarin.Forms.Forms.SetFlags("FastRenderers_Experimental");
FFImageLoading.Forms.Platform.CachedImageRenderer.Init(true);- Open the
NorthDallas.Contacts.iOS\AppDelegate.csfile and add the following the beginning of theFinishedLaunchingmethod.
FFImageLoading.Forms.Platform.CachedImageRenderer.Init();- Go back to the
ContactListView.xamlfile and add the following toContentPagenode.
xmlns:ffimage="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
- Now you can add a caching image to your custom view cell.
- Update your
ViewCellwith the following.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ffimage:CachedImage Grid.Row="0"
Grid.Column="0"
WidthRequest="300"
HeightRequest="300"
Source="{Binding picture.large}"/>
<StackLayout Grid.Row="0"
Grid.Column="1">
<Label FontAttributes="Bold">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding name.last}" />
<Span Text=", " />
<Span Text="{Binding name.first}" />
</FormattedString>
</Label.FormattedText>
</Label>
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding location.city}" />
<Span Text=", " />
<Span Text="{Binding location.state}" />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</Grid>As you scroll through the ListView, you will notice that some of the images look like a previous image until it has a chance to finish loading. To fix this, you wil need to add a LoadingPlaceHolder tag.
- Add the
LoadingPlaceholdertag to theCachedImagenode.
LoadingPlaceholder="http://placekitten.com/300/300"
- Run the application.
To keep up with trends, mobile applications have be updated regularly. One of the latest trends is circular images. It is easy to add a circular transformation with Fast & Furious Image Loading.
- In the
NorthDallas.ContactsSolution, right click the project and selectManage NuGet Packages for Solutionfrom the context menu. - Click on the
Browsetab - Type the following into the search
Xamarin.FFImageLoading.Transformations - In the right pane, select all the projects and click
Install - In the
NorthDallas.ContactsSolution, right click the project and selectManage NuGet Packages for Solutionfrom the context menu. - Go back to the
ContactListView.xamlfile and add the following reference toContentPagenode.
xmlns:tranformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
- Add a
CircleTransformationto theCachedImage.
<ffimage:CachedImage Grid.Row="0"
Grid.Column="0"
WidthRequest="300"
HeightRequest="300"
Source="{Binding picture.thumbnail}"
LoadingPlaceholder="http://placekitten.com/300/300">
<ffimage:CachedImage.Transformations>
<tranformations:CircleTransformation />
</ffimage:CachedImage.Transformations>
</ffimage:CachedImage>This is the first step towards creating a detail page. Once we have a detail page, we will enable the user to navigate to the detail by selecting an item in the ListView.
- Now right click that folder and select
Add > Class - Enter the name
ContactDetailViewModel.csand clickAdd - Make
ContactDetailViewModelimplementINotifyPropertyChangedusingMvvmHelpers
public class ContactDetailViewModel
: BaseViewModel
{
public ContactDetailViewModel(Result contact)
{
Contact = contact;
Title = $"{contact.name.first} {contact.name.last}";
}
public Result Contact { get; set; }
}We need to create a view to display the details of the contact.
- Right click the folder
Viewsand chooseAdd > New Itemfrom the context menu. - Select the template
Xamarin.Forms > Content Pageand enter the nameContactDetailView.xamland clickAdd.
- Replace the XAML for
ContactDetailView.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ffimage="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:tranformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations"
x:Class="NorthDallas.Contacts.Views.ContactDetailView"
Title="{Binding Title}">
<ContentPage.Content>
<ScrollView>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="300" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ffimage:CachedImage Grid.Row="0"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
Source="{Binding Contact.picture.large}"
LoadingPlaceholder="http://placekitten.com/300/300"
Margin="50, 0, 50, 0">
<ffimage:CachedImage.Transformations>
<tranformations:CircleTransformation />
</ffimage:CachedImage.Transformations>
</ffimage:CachedImage>
<StackLayout Grid.Row="1" Margin="10, 0, 10, 0">
<Label FontSize="Micro">Name:</Label>
<Label FontAttributes="Bold"
FontSize="Large">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Contact.name.last}" />
<Span Text=", " />
<Span Text="{Binding Contact.name.first}" />
</FormattedString>
</Label.FormattedText>
</Label>
<Label FontSize="Micro">Location:</Label>
<Label FontAttributes="Bold"
FontSize="Large">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Contact.location.city}" />
<Span Text=", " />
<Span Text="{Binding Contact.location.state}" />
</FormattedString>
</Label.FormattedText>
</Label>
<Label FontSize="Micro">Email:</Label>
<Label FontAttributes="Bold"
FontSize="Large"
Text="{Binding Contact.email}"/>
<Label FontSize="Micro">Phone:</Label>
<Label FontAttributes="Bold"
FontSize="Large"
Text="{Binding Contact.phone}"/>
<Label FontSize="Micro">Cell:</Label>
<Label FontAttributes="Bold"
FontSize="Large"
Text="{Binding Contact.cell}"/>
</StackLayout>
</Grid>
</ScrollView>
</ContentPage.Content>
</ContentPage>- Add a constructor parameter for
ContactDetailViewinNorthDallas.Contacts\Views\ContactDetailView.xaml.cs
public ContactDetailView (ContactDetailViewModel viewModel)
{
BindingContext = viewModel;
InitializeComponent ();
}Now it's time to wire everything up.
- Open the
ContactListView.xamlfile. - Add
ItemSelected="OnContactSelected"to theListViewnode inside of the file. - Open the
ContactListView.xaml.csfile under theContactListView.xamlpage. - Add a new method to the class to handle the
ItemSelectedevent.
private void OnContactSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem is Result)
{
Navigation.PushAsync(new ContactDetailView(new ContactDetailViewModel((Result)e.SelectedItem)));
var listView = (ListView)sender;
listView.SelectedItem = null;
}
}- Open the
App.xaml.csfile under theApp.xamlinside of your project. - Wrap the
MainPagewith a new instance ofNavigationPage.
MainPage = new NavigationPage(new ContactListView());