Building a Xamarin Forms Cross Platform Application Completely in F#

Inspiration

This post was inspired by this blog post by Scott Nimrod, @bizmonger.  He was building an Xamarin Forms trading application, FnTrade, using F#, but the root application projects were C# projects.  I was curious why that was.   So I asked him on Twitter.

Xamarin forms twitter challenge

To Scott, thank you for inspiring me to learn more about Xamarin Forms, and F#, and to write this post.

Building a Xamarin Forms Application in F#

You may or may not have worked with Xamarin forms in the past, but at the time of this writing, Visual Studio only offers Xmararin Forms Cross-Platform project templates in C#. We will see how we can take that C# project template and create an analogous F# project template. The C# cross platform templates give us the ability to target Android, iOS, Windows Phone 8, Windows 8.1, and Windows 10 UWP. The F# application we are building will only include Android and iOS.  The code for this post is on GitHub.   You may also wish to watch the step-by-step video Building A Xamarin Forms Cross Platform App In F#.

Disclaimer: At this time its only possible to build Xamarin Forms applications completely in F# for Android and iOS so we are going to ignore all the windows platforms in this particular blog post. The issue at this point in time, is the Windows Store requires the applications you submit to be compatible with .NET Native, and the F# and .NET Native teams have not at this point figured out how to get F# to work 100% with .NET Native and therefor its not supported.

With that in mind let’s begin. First we’ll need to create a cross platform C# Xamarin Forms application. In order to do that of course you will need the Xamarin For Visual Studio installed in Visual Studio 2015 Update 3. Note: There is a free version of Visual Studio, Visual Studio Community Edition that will work perfectly well for working with Xamarin Forms. So if you don’t have Visual Studio installed and you don’t have an MSDN account, I suggest you use that version.

Creating a C# Cross Platfrom Xamarin Forms Application

The first thing we need to do is create a new C# cross platform Xamarin Forms Xaml Portable application. We will use this to guide us through the creation of our all F# cross platform Xamarin Forms portable Android and iOS Application.
When creating a new project, we will find the Xamarin cross platform applications under the Tempaltes -> C# -> cross-platform node of the New Project dialog. There are several choices here, for this task we will select the one labeled “Blank Xaml App (Xamarin.Forms Portable)”, as seen below.

C# Cross Platfrom Template Selection

We will enter the Project Name as “CSharpCrossPlatformXamarinForms” and enter the solution name as “CrossPlatformXamarinForms”.

After creating the project we will see a few other dialogs. The first is a Windows 10 dialog asking what version of Windows 10 to target in your project.

Windows 10 Target Dialog

We aren’t going to be targeting windows 10 with our F# application so just hit the cancel button.

Now if we look at the Solution Explorer Window we will see all of the projects that were created for us.

  • CShapCrossPlatformXamarinForms(portable)
  • CShapCrossPlatformXamarinForms.Droid
  • CShapCrossPlatformXamarinForms.iOS
  • CShapCrossPlatformXamarinForms.Windows(Windows 8.1)
  • CShapCrossPlatformXamarinForms.WinPhone(Windows Phone 8.1)

Xamarin Forms Initial CSharp Sln Explorer

With this application we won’t be targeting any Windows Platforms because of the lack of complete support for F#. So lets remove the two Windows Projects from the solution.

That leaves us with only three projects.

  • CShapCrossPlatformXamarinForms(portable)
  • CShapCrossPlatformXamarinForms.Droid
  • CShapCrossPlatformXamarinForms.iOS

At this point lets run the Droid project just to make sure everything compiles and we can see what the expected output is. First we need to set CShapCrossPlatformXamarinForms.Droid as the Start Project. Right click on the CShapCrossPlatformXamarinForms.Droid in Solution Explorer and choose “Set as Startup Project”.

Set C# Droid as Start Up Project

Next we’ll run the application by clicking the infamous green Debug button or hitting F5. This will run the sample C# Android application. It should look like this.

C# Hello From Xamarin Forms

Now lets create the F# version of this application.

Creating a F# Cross Platfrom Xamarin Forms Application

The current Project structure for the C# Cross Platform Application currently contains only three projects.

  • CShapCrossPlatformXamarinForms(portable)
  • CShapCrossPlatformXamarinForms.Droid
  • CShapCrossPlatformXamarinForms.iOS

Xamarin Forms Initial CSharp Sln Explorer

We are going to mimic that structure using F# project templates. We will let the C# implementation guide us through the majority of this process. We will go through each project one by one creating each required project and then adding the required files to them. When we have completed this we’ll have a Xamarin Forms application written only in F#.

The F# portable library

The first project we need to create is the portable library. Since we already have a solution lets add an existing project to it. To do this, in solution explorer, we will right click on the Solution and select Add -> New Project.

Add New Project

While in the Add New Project dialog we will navigate to the F# node and select the “Portable Library (.NET 4.5, Windows Store, Xamarin)” project template. We then enter the name of the project “FSharpCrossPlatformXamarinForms”, and click ok.

Create F# Portable Project

The portable template gives us several files.

  • Assembly.fs
  • Portable.fs
  • Script.fsx

The only file that we want to keep is the Assembly.fs, so we’ll delete the other two files. Now that we basically have an empty project lets figure out how the C# portable project works. The first place to look is at the references. The C# portable library contains the following references.

  • .NET
  • Xamarin.Forms.Core
  • Xamarin.Forms.Platform
  • Xamarin.Forms.Xaml

Xamarin C# Portable References

Our F# library doesn’t have any of those. Lets dive further by looking at the properties of the Xamarin.Froms.Core reference to see where that assembly is located. We do this by right clicking on the Xamarin.Forms.Core and selecting “Properties” from the context menu, optionally we can left click on the reference and hit F4. The Path value in the Properties window shows the path to be “F:\code\CrossPlatformXamarinForms\packages\Xamarin.Forms.2.3.3.180\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Core.dll”.

Xamarin Forms Package Path

This tells us that there is a Nuget package called Xamarin.Forms that contains the Xamarin.Forms.Core assembly that is being referenced in the project. If we looked at the path of the other referenced assemblies we would find that they also are apart of the Xamarin.Forms Nuget package.

This means that we need to add the Xamarin.Forms Nuget package to our F# Portable library. Lets do that now. First right click on the references in the F# portable library project, and select “Manage Nuget Packages” from the list.

F# manage nuget packages

This will bring up a Nuget tab in the main Visual Studio window. Select the Browse option in the upper left hand corner. This will display a list of popular nuget packages to add to the project. We want to add the Xamarin.Forms nuget package. So lets enter Xamarin.Forms into the search box, and hit enter. this will list all the Nuget packages that start with Xamarin.Forms. The firs entry is likely what we want. Select it, and then in the right hand side click on the “install” button.

Install Xamarin Forms Nuget Package

Now that we have Xamarin.Forms installed we can add the required files to our portable library. For this we will need to reference the C# portable library. It currently contains seven files.

  • Assembly.cs
  • App.xaml
  • App.xaml.cs
  • GettingStarted.Xamarin
  • MainPage.xaml
  • MainPage.xaml.cs
  • packages.config

Our F# project currently has the following files.

  • Assembly.fs
  • packages.config.

App.xaml

We need to have a similar set of files to the C# portable library so lets start by adding the App.Xaml file to our F# portable project. We will do this by right clicking on the project and selecting Add -> New Item. If you look through the available Item templates for F# you will notice there is not a Xaml file template. In this case we will just navigate to the general section and add a text file named App.xaml.

Add App.xaml

Now that we have an App.xaml file we need to add some text to it. We can actually borrow the text from the App.xaml in the C# portable library. It looks like this.

<?xml version="1.0" encoding="utf-8"?>
<application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:class="CSharpCrossPlatformXamarinForms.App">
	<Application.Resources>
    <!-- Application resource dictionary -->
    </Application.Resources>
</application>

Copy and paste the code from the C# portable library’s App.xaml into the F# portable App.xaml file. Next we need to change one thing. the x:Class attribute must be set to the namespace of the app so it should be set to “FSharpCrossPlatformXamarinForms.App”.
Here is the updated F# portable App.xaml.

<?xml version="1.0" encoding="utf-8"?>
<application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:class="FSharpCrossPlatformXamarinForms.App">
	<Application.Resources>
	<!-- Application resource dictionary -->
	</Application.Resources>
</application>

There is one thing left to do with this file. All xaml files in Xamarin need to have a build action of Embedded Resource. We can set this by right clicking on the App.xaml file selecting “Properties” from the menu and for the “Build Action” select “Embedded Resource”.

Set App.xaml to Embedded Resource

App.xaml.fs

Now that we have an App.xaml file, we need a type that it can bind to. So let’s create a new F# source file by right clicking the F# portable project and selecting Add -> New Item. In the New Item Dialog select the code node and the “source file” template. Enter the App.xaml.fs as the file name and click the Add button.

Add App.xaml.fs

We have already defined what the name of that type is. In this case it’s “FSharpCrossPlatformXamarinForms.App”. The first part of that is simply the namespace “FSharpCrossPlatformXamarinForms” after the do is the type, “App”. Let look at the contents of the corresponding C# file and then translate that into F#.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Forms;
namespace CSharpCrossPlatformXamarinForms
{
	public partial class App : Application
	{
		public App()
		{
			InitializeComponent();
			MainPage = new CSharpCrossPlatformXamarinForms.MainPage();
		}

		protected override void OnStart()
		{
			// Handle when your app starts
		}

		protected override void OnSleep()
		{
			// Handle when your app sleeps
		}

		protected override void OnResume()
		{
			// Handle when your app resumes
		}
	}
}

The translated code for the App.xaml.fs file will look like this.

namespace FSharpCrossPlatformXamarinForms

open Xamarin.Forms
open Xamarin.Forms.Xaml

type App() = 
    inherit Application()

    do base.LoadFromXaml(typeof<App>) |> ignore
       base.MainPage <- new FSharpCrossPlatformXamarinForms.MainPage()
    
    override this.OnStart() = ()  // Handle when your app starts
    
    override this.OnSleep() = () // Handle when your app sleeps
    
    override this.OnResume() = () // Handle when your app resumes

There are a few things in the .fs file that might appear odd. First we opened the Xamarin.Forms.Xaml namespace. The second odd thing is the line with the call to LoadFromXaml. The reason we did these things is very simple. In the .cs file there is a call to InitializeComponent(). InitializeComponent is defined in a partial class in C# and it calls an extension method called LoadFromXaml.
So instead of creating a wrapper function around LoadFromXaml which in F# would just be a waste of code, we simply call LoadFromXaml directly. And it happens to be defined in the Xamarin.Forms.Xaml namespace. This technique will be repeated for all the types that are bound to Xaml files.

GettingStarted.Xamarin

If you want to include the GettingStarted.Xamarin file in your portable project for parity sake, please do. Simply copy it from the C# portable project into your F# portable project.

MainPage.xaml

Now we can add the MainPage.xaml file to our F# portable project. Like we did with the App.xaml file, add a new text file to the F# Portable project and name it MainPage.xaml.

Let’s examine the contents of the MainPage.xaml file in the C# portable project this time, and see how much we can borrow for our F# version.

<?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:local="clr-namespace:CSharpCrossPlatformXamarinForms" x:class="CSharpCrossPlatformXamarinForms.MainPage">
	<label text="Welcome to Xamarin Forms!" verticaloptions="Center" horizontaloptions="Center"></label>
</contentpage>

This again we can borrow most of this code although we need to change both the namespace and the class this time. The resulting F# version will be.

<?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:local="clr-namespace:FSharpCrossPlatformXamarinForms" x:class="FSharpCrossPlatformXamarinForms.MainPage">
	<label text="Welcome to Xamarin Forms!" verticaloptions="Center" horizontaloptions="Center"></label>
</contentpage>

We can simply paste the corrected version of the code into our new MainPage.xaml file. Now that we did this, we also need to set this file’s build action to “Embedded Resource”.

MainPage.xaml.fs

Like we did with App.xaml.cs, we’ll create a new source file with the name MainPage.xaml.fs. Now lets look at the C# version of this and again translate it to F#.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace CSharpCrossPlatformXamarinForms
{
	public partial class MainPage : ContentPage
	{
		public MainPage()
		{
			InitializeComponent();
		}
	}
}

The F# translation looks like this.

namespace FSharpCrossPlatformXamarinForms

open Xamarin.Forms
open Xamarin.Forms.Xaml

type MainPage() = 
    inherit ContentPage()
    
    do base.LoadFromXaml(typeof<MainPage>) |> ignore

The only thing different about this type is it inherits from ContentPage, and not Application. The App type inherits from Application because it is the entry point of the app.

File Order Matters

If you were to try to compile the F# portable library at this point, it wouldn’t compile. The reason is in F# code that gets called must be defined before the calling code. In this case, MainPage has not yet been defined when App tries to instantiate it. In visual studio there is a very simple way to fix this. If you right click on MainPage.xaml.fs and select “Move Up” it will move the file above the file above it in the project file list. We need to do this until it is above App.xaml.fs. Alternatively you can use Alt + Up arrow.

MainPage.xaml.fs Move Up

Now our F# portable library is complete. So let’s get started on the F# droid application.

The F# Droid Application

Disclaimer: Xamarin can be tricky to get working. In this blog post I am compiling and running against Android 7.0 and I’m using an x86 Android 7.0 emulator I may do a future blog post about updating Xamarin for Android

The first thing we need to do is add a Droid project to our Solution. If we add a Project to the solution like before, we’ll be presented with only one obvious option for this project type. “Blank pp (Android)”. We select the template and enter the name “FSharpCrossPlatformXamarinForms.Droid” for the project name and click the OK button.

Create F# Droid Project

Just as before with the portable project let’s look at the references of the C# version of the droid project.

  • CSharpCrossPlatformXamarinForms
  • FormsViewGroup
  • Mono.Android
  • mscorlib
  • System
  • System.Core
  • System.ObjectModel
  • System.Xml
  • System.Xml.Linq
  • Xamarin.Android.Support.Design
  • Xamarin.Android.Support.v4
  • Xamarin.Android.Support.v7.AppCompat
  • Xamarin.Android.Support.v7.CardView
  • Xamarin.Android.Support.v7.MediaRouter
  • Xamarin.Android.Support.v7.RecycleView
  • Xamarin.Forms.Core
  • Xamarin.Forms.Platform
  • Xamarin.Forms.Platform.Android
  • Xmaarin.Forms.Xaml

The F# Droid project in comparison starts out with the following references.

  • FSharp.Core
  • Mono.Android
  • mscorlib
  • System
  • System.Core
  • System.Xml

We might want to look at all the references in the C# project to figure out where all those Xamarin.Android.* references come from. Since there are so many, I’ll just tell you they are all in the Xamarin.Forms Nuget package. So the next thing we should do is add the Xamarin.Forms Nuget package to the Droid project.

Once we have done that we will have the matching references we were missing. At the time of this post there is a bug in the Android F# template, which requires one additional Nuget package to fix. So lets go ahead and add it now. The Nuget package is named Xamarin.Android.FSharp.ResourceProvider. Add it just like you did the Xamarin.Forms Nuget package.

Add F# Droid Resource Provider package

Adding Assets and Resources

If you look at the C# Droid project there are a few folders in the projects. Assets, and Resources. Those hold files specific to Android for images and defining resources that can be used in your Android application. For our purposes we can simply copy all the files in each of those folders into our F# Droid project.

Note: By default there are a few existing files in our project that we don’t need. They are located in the following places.

  • Resources\Resource.designer.fs
  • Resources\layout\main.xaml
  • Resources\values\string.xml
  • GettingStarted.Xamarin

The Resources\Resource.designer.fs file is autogenerated, so we’ll deal with that one in a special way after we have all the files we need for this project.

The other two files main.xaml and string.xaml we will just delete. We can also get rid of GettingStarted.Xamarin as we have it in our portable project and that is the root of a Xamarin.Forms app.

MainActivity.fs

The Droid project gave us the only fs file that we need for this app however its contents need to be modified. Lets look at the C# Droid’s MainActivity.cs to figure out what needs to change.

using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
namespace CSharpCrossPlatformXamarinForms.Droid
{
	[Activity(Label = "CSharpCrossPlatformXamarinForms", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
	public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
	{	
		protected override void OnCreate(Bundle bundle)
		{
			TabLayoutResource = Resource.Layout.Tabbar;
			ToolbarResource = Resource.Layout.Toolbar;
			base.OnCreate(bundle);

			global::Xamarin.Forms.Forms.Init(this, bundle);
			LoadApplication(new App());
		}
	}
}

The translation to F# looks like this

namespace FSharpCrossPlatformXamarinForms.Droid
open System
open Android.App
open Android.Content
open Android.Content.PM
open Android.OS
open Android.Runtime
open Android.Views
open Android.Widget
open Xamarin.Forms
open Xamarin.Forms.Platform.Android
open FSharpCrossPlatformXamarinForms
type Resources = FSharpCrossPlatformXamarinForms.Droid.Resource
[<Activity(Label = "XamarinFormsFSharpDemo.Droid", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = (ConfigChanges.ScreenSize ||| ConfigChanges.Orientation))>]
type MainActivity () =
	inherit FormsAppCompatActivity()
	
	override this.OnCreate (bundle) =

		FormsAppCompatActivity.TabLayoutResource <- Resources.Layout.Tabbar

		FormsAppCompatActivity.ToolbarResource <- Resources.Layout.Toolbar

		base.OnCreate (bundle)

		Forms.Init(this,bundle)

		base.LoadApplication(new App())

A lot of this looks very similar to the C# version of the code except for one part. The assignment of the Resources is done through a TypeProvider. Its declared as type Resources = XamarinFormsFSharpDemo.Droid.Resource. That functionaility came when we added the extra Nuget package. It is neccessary to deal with on specific issue. The Resources\Resource.designer.fs file that comes with the default F# Droid template is generated by codedom, and in doing so it generate a few F# key words ad constants which are intended do be used for programmatic access to Android resource values. Since key words are being used, the code doesn’t compile. The syntax for the MainActivity.fs above is correct but we still have a few issues.

Fixing the Droid.fsproj file.

When adding the resource files to the F# Droid project some of them may have gotten out of order in the fsproj file. The Droid project prefers that files in the same directory come in order in an item group. Here is an example of a valid Droid fsproj file’s item groups.

 <itemgroup>
	<none include="Resources\AboutResources.txt"></none>
	<androidresource include="Resources\drawable\Icon.png"></androidresource>
    <androidresource include="Resources\drawable-hdpi\icon.png"></androidresource>
    <androidresource include="Resources\drawable-xhdpi\icon.png"></androidresource>
    <androidresource include="Resources\drawable-xxhdpi\icon.png"></androidresource>
	<androidresource include="Resources\layout\Tabbar.axml"></androidresource>
    <androidresource include="Resources\layout\Toolbar.axml"></androidresource>
	<androidresource include="Resources\values\styles.xml"></androidresource>
  </itemgroup>
  <itemgroup>
	<compile include="Properties\AssemblyInfo.fs"></compile>
    <none include="Properties\AndroidManifest.xml"></none>
  </itemgroup>
  <itemgroup>
    <androidasset include="Assets\AboutAssets.txt"></androidasset>
    <compile include="MainActivity.fs"></compile>
    <content include="packages.config"></content>
  </itemgroup>
 

We should make the project files conform to something like this.

The last issue to deal with is that pesky Resource.Designer.fs file. In the .fsproj markup we should be able to fine the line that looks like this.
Resources\Resource.designer.fs

We need to do something a bit strange. We want to make that a .cs file. So change it to

Resources\Resource.designer.cs

Also if you didn’t do so already you want to remove it from any that is maybe apart of. Above we have already removed it.

The F# iOS Application

DISCALIMER: At the time of this writing I do not currently have access to a mac, nor time to figure out mac in cloud. The following code is simply the translation from C# to F# for the purposes of this blog post. I do plan on figuring out how to set up a mac in the cloud so that I can test these scenarios in the future.
marin
Just like we did with Android we’ll need to create an F# iOS application to get us started. In theory this is going to be easy. So we will Add an Existing Project like before by right clicking solution explorer selecting Add -> New Project.

We will select “Blank App (iOS)” from the available iOS project templates. Enter FSharpCrossPlatformXamarinForms.iOS for the project name and click “OK”.

Create F# iOS Project

The first thing to do is compare the projects references. The C# iOS app has the following references.

  • CSharpCrossPlatformXamarinForms
  • System
  • System.Core
  • System.Xml
  • Xamarin.Forms.Core
  • Xamarin.Forms.Platform
  • Xamarin.Forms.Platform.iOS
  • Xamarin.Forms.Xaml
  • Xamarin.iOS

The F# iOS project currently has the following references.

  • System
  • System.Core
  • System.Xml
  • Xamarin.iOS

Its pretty obvious what we have to add to this project now to make this the same. First we need to reference our portable class library “FSharpCrossPlatformXamrinForms”. We can do that by right clicking on references and selecting “Add Reference” and then checking the box next to FSharpCrossPlatformXamrinForms project.

Add Portable Library Reference to iOS Project

Now our F# iOS project references look a little close to the C# project.

  • FSharpCrossPlatformXamarinForms
  • System
  • System.Core
  • System.Xml
  • Xamarin.iOS

Add the Xamarin.Forms Nuget package

We just need to add the Xamarin.Forms Nuget package to finish off the references. As before right click on the references and select Manage Packages, search for Xamarin.Forms and install the nuget package.

Install Xamrin.Forms Nuget package into the iOS Project

  • FSharpCrossPlatformXamarinForms
  • System
  • System.Core
  • System.Xml
  • Xamarin.Forms.Core
  • Xamarin.Forms.Platform
  • Xamarin.Forms.Platform.iOS
  • Xamarin.Forms.Xaml
  • Xamarin.iOS

The C# project has many additional resource files, so we just need to copy and paste them from the resources folder and add them to the F# project. The simplest way to do this is to copy the files into the new directory, then modify the .iOS.fsproj file to include all the resources. You can copy the BundleResource items from ItemGroup in the iOS.csproj file to make it simpler.

	<bundleresource include="Resources\Default-568h%402x.png"></bundleresource>
	<bundleresource include="Resources\Default-Portrait.png"></bundleresource>
	<bundleresource include="Resources\Default-Portrait%402x.png"></bundleresource>
	<bundleresource include="Resources\Default.png"></bundleresource>
	<bundleresource include="Resources\Default%402x.png"></bundleresource>
	<bundleresource include="Resources\Icon-60%402x.png"></bundleresource>
	<bundleresource include="Resources\Icon-60%403x.png"></bundleresource>
	<bundleresource include="Resources\Icon-76.png"></bundleresource>
	<bundleresource include="Resources\Icon-76%402x.png"></bundleresource>
	<bundleresource include="Resources\Icon-Small-40.png"></bundleresource>
	<bundleresource include="Resources\Icon-Small-40%402x.png"></bundleresource>
	<bundleresource include="Resources\Icon-Small-40%403x.png"></bundleresource>
	<bundleresource include="Resources\Icon-Small.png"></bundleresource>
	<bundleresource include="Resources\Icon-Small%402x.png"></bundleresource>
	<bundleresource include="Resources\Icon-Small%403x.png"></bundleresource>

You probably want to include in the same item group with your other resources as well. So just move it.

Next we’ll compare the files in the project. There are only 2 .cs files in the C# iOS project and they correspond to 2 .fs files in the F# project. Lets deal with them one at a time.

AppDelegate.fs

The C# AppDelegate class looks like

using System;
using System.Collections.Generic;
using System.Linq;

using Foundation;
using UIKit;

namespace CSharpCrossPlatformXamarinForms.iOS
{
    // The UIApplicationDelegate for the application. This class is responsible for launching the 
    // User Interface of the application, as well as listening (and optionally responding) to 
    // application events from iOS.
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
    {
        //
        // This method is invoked when the application has loaded and is ready to run. In this 
        // method you should instantiate the window, load the UI into it and then make the window
        // visible.
        //
        // You have 17 seconds to return from this method, or iOS will terminate your application.
        //
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }
    }
}

Translating that to F# is pretty straight forward. We ahve seen most of this before in the Android project.

namespace FSharpCrossPlatformXamarinForms.iOS

open System
open UIKit
open Foundation
open Xamarin.Forms
open Xamarin.Forms.Platform.iOS

[<Register ("AppDelegate")>]
type AppDelegate () =
    inherit FormsApplicationDelegate ()

    let window = new UIWindow (UIScreen.MainScreen.Bounds)

    // This method is invoked when the application is ready to run.
    override this.FinishedLaunching (app, options) =
        // If you have defined a root view controller, set it here:
        // window.RootViewController <- new MyViewController ()
       do Forms.Init()

       base.FinishedLaunching(app, options)

Main.fs

The C# code for Main.cs looks like this.

using System;
using System.Collections.Generic;
using System.Linq;

using Foundation;
using UIKit;

namespace CSharpCrossPlatformXamarinForms.iOS
{
    public class Application
    {
        // This is the main entry point of the application.
        static void Main(string[] args)
        {
            // if you want to use a different Application Delegate class from "AppDelegate"
            // you can specify it here.
            UIApplication.Main(args, null, "AppDelegate");
        }
    }
}

And the F# translation is

namespace FSharpCrossPlatformXamarinForms.iOS

open UIKit

module Main =
	[<entrypoint>]
	let main args =
		UIApplication.Main(args, null, "AppDelegate")
		0

This code didn’t have to change at all.

You now should be able to build iOS and Android Xamarin Forms applications only using F#.

Disclaimer: This is just creating a version of the existing C# Xamarin Forms project templates in F#, there may be scenarios that you run into that don’t work after starting with this approach.

Best of luck, and happy coding!

Spread The Word
Adam.Wright
 

Adam Wright is a technologist specializing in software development using Microsoft technologies.

Click Here to Leave a Comment Below 0 comments