In the last post about Xamarin Forms we’ve started to see the basic concepts on how to begin the development of a cross-Platform application. In this post we’re going to explore some basic navigation concepts and some tips to organize our solution. Also, we’ll develop a simple CrossPlatformApp that welcomes us with a main screen and a button to navigate to a new view where we can generate a random integer.
Organize our new project
We’ve just created a new Xamarin Forms Project and now we’re ready to develop yet another mobile app. If you know how to create a brand new Xamarin Forms Project you can continue reading, otherwise I suggest to read the first post (getting started) of this serie.
When I start a new Project I like to organize things to be more confortable and organized so let’s start and do it.
The Views folder
We create a new folder in the shared Project and call it Views. In this folder we’ll put all the files to create the UI (the views).
We already have a view in our Project: the MainPage.xaml. We move the file in the Views folder.
Now we move the MainPage class in the Views namespace. Besides, everytime we’ll add a new file in the Views folder the class will be created in the Views namespace as standard behavior by Visual Studio.
To move the MainPage class into the Views namespace we edit MainPage.xaml and MainPage.xaml.cs like this:
Now our Project won’t compile because the App class cannot find the MainPage class anymore. So we need to edit the App class like the following image:
Now our soution compiles.
Setup the navigation
With navigation we mean the features available in Xamarin Forms to drive the user experience from a view to another. In this example we’re going to implement a hierarchical navigation.
To support hierarchical navigation we create a shell for our UI where the views will be navigated. The shell is created with an instance of the NavigationPage class. So we edit the App.xaml.cs file to set the MainPage of the App as a new NavigationPage. The root of our navigation is the MainPage that is a ContentPage.
If we build and run our application we’ll see no UI differences in the app but now we’re ready to navigate from one page to another.
The CrossPlatformApp for UWP.
Let’s navigate
As we stated at the beginning of this post the app has to show to the user a button to navigate to another view. So let’s edit the XAML in the MainPage class to do this.
[code language=“XML”]
/>
/>
/>
[/code]
In the respective code-behind file (MainPage.xaml.cs) we write:
[code language="csharp"]
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnStartClicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new RandomIntegerView(new RandomIntegerViewModel(new RandomGenerator())));
}
}
[/code]
In the code above we trigger the navigation in the handler of the click event of the button. We use the Navigation property to get a reference to the Navigation system and then we call PushAsync to put the view where we'll generate a random number on the stack of the hierarchical navigation.

Before we move on we give a closer look this line of code:
```
await Navigation.PushAsync(new RandomIntegerView(new RandomIntegerViewModel(new RandomGenerator())));
```
Here we're creating an instance of the RandomIntegerView passing in the constructor the ViewModel and in its constructor a reference to a service which can generate random numbers. Then we push this view onto the navigation stack.
We now have some errors from the compiler because we've written some names of not existing classes. We move on and create those classes.
In the Views folders we create a new **RandomIntegerView** class like this:

In the **RandomIntegerView.xaml** file we write:
[code language="xml"]
>
>
>
>
>
[/code]
We now have our view to generate random numbers composed by a generic label that states what to view does (generate a number), a button to trigger the number calculation, and a label which displays the lucky number.
The code-behind of the view is:
[code language="csharp"]
using CrossPlatformApp.ViewModels;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace CrossPlatformApp.Views
{
public partial class RandomIntegerView : ContentPage
{
public RandomIntegerView(RandomIntegerViewModel viewModel)
{
BindingContext = viewModel;
InitializeComponent();
}
}
}
[/code]

_UWP flavor of the random integer generator_
As we can see from the XAML code we use the MVVM pattern with binding to link the action of the "Generate" button to a Command that will handle the number generation in the ViewModel. The visualization of the result is performed with a label with binding in the Text property to a LuckyNumber member of the ViewModel.
### The RandomIntegerViewModel and the .Core project
Now we need the **RandomIntegerViewModel** to give life to our UI. We create a **ViewModels** folder in the shared Project and create a new class into it named **RandomIntegerViewModel**.

We also create a new .NET Standard assemply Project called **CrossPlatformApp**.**Core** where we'll put all the services and interfaces definition that our app will need.

Inside this new Project we create an interface that states what a lucky number generator has to do: we call it *IIntegerGenerator* and the code is:
[code language="csharp"]
namespace CrossPlatformApp.Core
{
public interface IIntegerGenerator
{
int GenerateInt();
}
}
[/code]
Now we create a **RandomGenerator** class that implements *IIntegerGenerator* like this:
[code language="Csharp"]
using System;
namespace CrossPlatformApp.Core
{
public class RandomGenerator : IIntegerGenerator
{
public int GenerateInt()
{
Random r = new Random(DateTime.Now.Second);
return r.Next();
}
}
}
[/code]
The final result is:

Now we can go back to our **RandomIntegerViewModel** and write:
[code language="csharp"]
using CrossPlatformApp.Core;
using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
namespace CrossPlatformApp.ViewModels
{
public class RandomIntegerViewModel : INotifyPropertyChanged
{
private ICommand \_generateRandomInteger;
private IIntegerGenerator \_integerGeneratorService;
private int \_luckyNumber;
public RandomIntegerViewModel(IIntegerGenerator integerGeneratorService)
{
\_integerGeneratorService = integerGeneratorService;
}
public event PropertyChangedEventHandler PropertyChanged;
public ICommand GenerateRandomInteger
{
get
{
if (\_generateRandomInteger == null)
{
\_generateRandomInteger = new Command(() =>
{
LuckyNumber = \_integerGeneratorService.GenerateInt();
});
}
return \_generateRandomInteger;
}
}
public int LuckyNumber
{
get
{
return \_luckyNumber;
}
private set
{
if (\_luckyNumber != value)
{
\_luckyNumber = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LuckyNumber)));
}
}
}
}
}
[/code]
What we've done is to define the Command (the **GenerateRandomInteger** Command) to generate the lucky number and the property to allow the display of the result in the view (the **LuckyNumber** property). As we can see we also injected into the constructor the dependency from the service that creates the random integer. This way our class is more testable. We implemented the *INotifyPropertyChanged* to enable the comunication from the ViewModel to the View.
Now we can hit F5 and try the app.

_The Android version of the app when running_
We can **navigate back** to the main page if we press the back button of the OS:

_Home sweet home (Android version)_
### TL; DR
In this post we created a simple app to handle the basics of the navigation mechanism and implement a hierarchical navigation.
We also organized our solution with a Core Project to host all the services and interfaces that are useful to all the three versions of our app. A core Project is useful because promotes code reuse and testability. We also explored the concept of services where we can implement non-UI features and inject them in our view-models.
**Source code**:
Ti è piaciuto questo articolo?
Iscriviti alla newsletter per ricevere contenuti su DevOps, software engineering e team di sviluppo direttamente nella tua casella di posta.
Utilizziamo cookie tecnici (necessari) e, con il tuo consenso, cookie analitici per migliorare la tua esperienza. Puoi leggere la nostra Privacy Policy e la Cookie Policy per maggiori dettagli.