Here lies a step-by-step tutorial on a small iOS/Android cross-platform app using Xamarin.Forms and Prism as an MVVM framework and architectural guide. This tutorial has been done with Xamarin Studio for Mac, so your experience will differ slightly if you are using Visual Studio on Windows. Some things are better/easier in Windows, others are better/easier on the Mac.

If you run into questions, feel free to ask me for some help! You can contact me through my website any time.

Launch Xamarin Studio

Open the Add-ins dialog to get the Prism template pack

Open the Add-ins dialog to get the Prism template pack

Install Prism template pack through Add-in Manager

Things don't seem to be totally dialed in yet for the Add-in Manager, so often when you search for 'prism', nothing will come up. Don't worry! We'll work around that in the following steps, below.

 

If you have some luck on your side, the Prism Template Pack will show up, and you simply click "Install...".

Download the Prism Template Pack Manually if Necessary

If luck is not on your side today, Prism will not show up. No big deal... We'll just install it manually.

First download the Prism Template Pack:  http://addins.monodevelop.com/Project/Index/226

Download the Prism Template Pack Manually if Necessary

Click on the "Install from file..." button

Install Add-in for Prism

XamarinStudio Warnings

Should this warning message pop up, it's ok to ignore. The Prism Template Pack for Mac is not quite as refined as the Windows version for Visual Studio.

XamarinStudio Warnings

Close the Add-in Manager

We've got our template pack installed now, which helps streamline development with Prism. You can close the Add-In Manager window now.

Time to Start a New Solution

Time to Start a New Solution

Select "Prism Unity App"

This is part of what the Prism Template Pack does for us:  App scaffolding templates so your customization efforts are minimized, and you can get on with writing your code.

Name & Configure Your App

Name & Configure Solution and Cross-Platform PCL (Portable Class Library)

License Acceptance

License Acceptance

The Three Musketeers

Notice the 3 projects in our solution:

  1. HelloXamarinForms2 is the cross-platform part of our app. For now, these are PCLs (Portable Class Libraries), however, in the not too distant future, PCLs will be going away and replaced by .NET Standard.
  2. HelloXamarinForms2.Droid is the Android-only component.
  3. HelloXamarinForms2.iOS is the iOS-only competent.
The Three Musketeers

Open the 'Packages' Folder of the PCL

Notice that lots of our Nuget packages need an update. I like to update the packages straight away. We'll do that in the next step.

Open the 'Packages' Folder of the PCL

Update Nuget Packages

  1. Right-click on the very top-level item, which is at the solution level, in order to update all packages for all 3 projects.
Update Nuget Packages

Go Grab a Coffee...

Updating all the Nuget packages may take a few minutes. You've got time! Crack open the 'Package Console' if you want to watch all the action as it happens.

Try to Build or Rebuild... I dare ya!

Spoiler alert:  It's not going to go terribly well.

Try to Build or Rebuild... I dare ya!

Fix the MainPageViewModel Namespace

Depending on your preferences, you may have an extra ".ViewModels" in the namespace. You should go ahead and delete that.

Fix the MainPageViewModel Namespace

Implement the INavigationAware Interface

The Prism template pack was made before some breaking changes were released later, so INavigationAware is not quite complete.

  1. Click on INavigationAware, and then hit alt-enter to bring up the quick-fix suggestions.
  2. Click 'Implement interface'.
Implement the INavigationAware Interface

Remove the NotImplementedException

When you tell Xamarin Studio to implement an interface, it will automatically add a line to throw a NotImplementedException. Let's get rid of it so we don't crash when navigating to the MainPage.

Remove the NotImplementedException

Fix the Namespace in MainPage.xaml

The class on line 7 should read, "HelloXamarinForms2.Views.MainPage", rather than "HelloXamarinForms2.Views.Views.MainPage". Remove the extra ".Views".

Fix the Namespace in MainPage.xaml

Remove the Extra ".Views" from the Code-Behind

Build Your Way to Compiling Code!

Try that build again... It won't work yet, but it will show us what we need to fix next!

Build Your Way to Compiling Code!

Add Using Statements to AppDelegate.cs

We're faced with several red underlines here... We'll start dealing with them in the next step.

Add Microsoft.Practices.Unity Using Statement

  1. Click on IUnityContainer.
  2. Hit alt-enter on the keyboard to bring up the quick-fix suggestions.
  3. Select 'using Microsoft.Practices.Unity'.

Add Prism Using Statement

  1. Click on IPlatformInitializer.
  2. Hit alt-enter, and select 'using Prism'.

Add Prism.Unity Using Statement

  1. Click on IPlatformInitializer.
  2. Hit alt-enter and select 'using Prism.Unity'.

Build

Still not quite there... Build again to reveal the next errors.

Hint:  The next issue will be in the Android startup class (MainActivity.cs), just like the last one was in the iOS startup class (AppDelegate.cs).

Build

MainActivity.cs: Our Next Issue

We'll fix these up in the next steps...

Add Microsoft.Practices.Unity Using Statement

  1. Click on IUnityContainer.
  2. Hit alt-enter.
  3. Select 'using Microsoft.Practices.Unity'.

Add Prism Using Statement

  1. Click on IPlatformInitializer.
  2. Hit alt-enter.
  3. Select 'using Prism'.

Add Prism.Unity Using Statement

  1. Click on IPlatformInitializer.
  2. Hit alt-enter.
  3. Select 'using Prism.Unity'.

We Can Rebuild it... We Have the Technology!

Start the mighty drum-roll as we hit Rebuild All one more time...

We Can Rebuild it... We Have the Technology!

Party-On, Wayne!

Party-On, Wayne!

Select the iOS Project to Run

Select the iOS Project to Run

Select 'Debug'

Select 'Debug'

Choose a Simulator

Run the App

The keyboard shortcut is command-enter. Hitting F5 will work as well.

Run the App

Phew... Made it!

Here we are at Hello World for a Xamarin.Forms app!

Phew... Made it!

Make this app our own

Let's get rid of the sample code provided in the MainPageViewModel.

Make this app our own

I Utterly Loathe Magic Strings

Let's delete the magic string on line 14. We'll replace it in the next step.

Replace Magic String

Customize MainPage.xaml

Remove the template-generated code, and add in the StackLayout and Button as shown here. We're setting the command "by intention" here with the "NavToTipCalculatorCommand". This command does not yet exist in our MainPageViewModel, but stay tuned... It will soon!

Customize MainPage.xaml

What's That 'Binding' Thing???

Back to slides for a quick look at MVVM and INotifyPropertyChanged.

Add New View for our Tip Calculator

  1. Right click on the "Views" folder.
  2. Add --> New File...
Add New View for our Tip Calculator

Add New View: TipCalculatorPage

Prism Template Pack Might Hork-Up The Namespaces: Fix the code-behind of our new view

Depending on your solution settings, when you add new views and/or viewModels, you could wind up with namespaces that duplicate the "Views" or "ViewModels" part of the namespace. Here, you can see that the namespace is set as "HelloXamarinForms2.Views.Views". Only one of those ".Views" should be there, so delete the extraneous one.

Prism Template Pack Might Hork-Up The Namespaces:  Fix the code-behind of our new view

Next Fix the Namespace in Xaml

Check out line 7 here... Once more, we have "Views.Views", so we need to get rid of the extra one.

Next Fix the Namespace in Xaml

All Views Must Be Registered for Navigation

Whenever you add a new view, you'll need to add it to the "RegisterTypes" method in App.Xaml.cs:

Add a Label to the TipCalculatorPage

This is just so that we can test navigating to this page, and know that we've landed in the right place:

Add a Label to the TipCalculatorPage

Add NavToTipCalculatorCommand to MainPageViewModel

Once more we are coding by intention:  The NavToTipCalculator handler does not exist yet, but we'll generate that handler in the next step.

Add NavToTipCalculatorCommand to MainPageViewModel

Generate NavToTipCalculatorCommand Handler: NavToTipCalculator

  1. Click on "NavToTipCalculator", which should be underlined in red for now.
  2. Hit alt-enter on your keyboard.
  3. Select the "Generate method..." option.

Remove the NotImplementedException

By default, when you generate your new method, you will see a NotImplementedException being thrown. Let's get rid of that so we don't crash when we run the app.

Remove the NotImplementedException

Introducing the Prism NavigationService

Prism's NavigationService helps us move from view to view throughout our application. Since we're using dependency injection in this app, we can simply ask for an INavigationService in the ViewModel constructor and Prism/Unity will make it happen. You never have to "new up" a navigation service, and it's easily mockable for unit testing. Amazing!

Introducing the Prism NavigationService

Add Navigation Logic to NavToTipCalculator in the MainPageViewModel

Note that "TipCalculatorPage" is underlined in red. We'll fix that next.

Add Navigation Logic to NavToTipCalculator in the MainPageViewModel

Add New Using Statement to MainPageViewModel

  1. Click on TipCalculatorPage.
  2. Hit alt-enter.
  3. Select "using HelloXamarinForms2.Views" to add the namespace.

You certainly don't have to do it this way. You could have just used a string, "TipCalculatorPage" and it would work just fine. However, I personally prefer adding the namespace and then not have to use magic strings.

Getting Ready to Add the TipCalculatorPageViewModel

  1. Right-click on the "ViewModels" folder.
  2. Add --> New File...
Getting Ready to Add the TipCalculatorPageViewModel

Create TipCalculatorPageViewModel

Assuming you want your views to automagically hook-up with their viewModels, there is a naming convention you must follow:

ViewModels must be named as:  MyCoolViewNameViewModel

Yes, you can change that convention if you want to.

Fix ViewModel Namespace

Again, the Prism Template Pack is not so perfect, and it may mess up your ViewModel namespace when you create new ones. Remove the extra ".ViewModels":

Fix ViewModel Namespace

Give it a Whirl!

Give it a Whirl!

Your MainPage

Not the most complex view you'll ever create, but it's a great start!

Try tapping on the "Tip Calculator" button to see if our navigation is working.

Your MainPage

Your TipCalculatorPage

Hopefully, it worked! Here we see the label we created, just to be able to identify that the correct view comes up when you try to navigate to it.

Just one problem:  We haven't left ourselves any way to return to the MainPage!

Your TipCalculatorPage

Navigate to a NavigationPage on App Launch

Previously, we were navigating to just the MainPage. By placing MainPage within a NavigationPage, we will automagically get the "navigate back" button.

Change the OnInitialized method of App.xaml.cs to next the MainPage within a NavigationPage.

Navigate to a NavigationPage on App Launch

Register NavigationPage in App.RegisterTypes Method

On line 19, you can see that we're registering a NavigationPage, even though we do not have any explicitly defined NavigationPage classes (both MainPage and TipCalculatorPage are subclasses of ContentPage rather than NavigationPage).

If you forget to register the NavigationPage, your app will crash on launch with a fairly cryptic error! On iOS this error will tell you, "NSInternalInconsistencyException Reason: Application windows are expected to have a root view controller at the end of application launch".

Add Using Statement for Xamarin.Forms

  1. Click on "NavigationPage" (it should be underlined in red).
  2. Hit alt-enter to bring up the quick-fix suggestions.
  3. Select "using Xamarin.Forms".

Let's Run the App

Let's Run the App

Notice we now have a header area, where the title of the page is displayed

We can change the title of the page to be absolutely anything we want.

Notice we now have a header area, where the title of the page is displayed

Tap the 'Tip Calculator' Button... Automatic Back Button!

By launching your MainPage nested in a NavigationPage, you now get a free bonus gift:  Back/forward buttons to navigate between pages!

Tap the 'Tip Calculator' Button... Automatic Back Button!

Wrap the Label in a StackLayout

In a ContentPage, the view can only hold 1 item. Typically you will use something like a Grid or StackLayout (both of which can hold multiple view items) as that single item, and then arrange them in whichever layout control you've chosen.

If you would like to learn more about your layout options, Xamarin's developer documentation provides a nice overview here.

Let's wrap the label we have in a StackLayout so that we can have more than just a label on the page:

Wrap the Label in a StackLayout

Add a Field For Users to Enter the Bill

See that new binding to the "BillAmount" property on line 18? Keep that in mind... We'll need to add a property to the TipCalculatorPageViewModel for this.

Add a Field For Users to Enter the Bill

Add a Tip Percent Slider and Label to Show Its Value

  • Use a horizontal StackLayout to put the two side-by-side.
  • Once again, make a mental note about the "TipPercentage" binding we're setting up here. We'll be adding a property to the TipCalculatorPageViewModel as well.
Add a Tip Percent Slider and Label to Show Its Value

Pro-Tip!

You'd better put that minimum value for your sliders before the maximum value. Otherwise it will completely mangle your view, and you may spend hours trying to figure out what you did wrong.

Like I did!

Pro-Tip!

Add Properties to ViewModel

  • TipPercentage
  • BillAmount
  • Initialize TipPercentage to 18 in the constructor.
Add Properties to ViewModel

Add the TipAmount to the View

Make a mental note of "TipAmount"... That's another property we'll need to add to the TipCalculatorPageViewModel.

Add the TipAmount to the View

Add TipAmount Property to TipCalculatorPageViewModel

Add TipAmount Property to TipCalculatorPageViewModel

Add a Method to Calculate the Tip to the TipCalculatorPageViewModel

Add a Method to Calculate the Tip to the TipCalculatorPageViewModel

Update the TipAmount Property Whenever TipPercentage or BillAmount Change

INotifyPropertyChanged to the rescue!

Run That App... Prepare for your Inevitable Fame & Glory!

Run That App... Prepare for your Inevitable Fame & Glory!

Ship It!

Ship It!