Cross Platform C#

Polyglot Apps for iOS, Android and Beyond

Did you know you can combine C#, F#, Visual Basic, Razor, HTML and JavaScript within a single app?

It's well known by now that you can use C# to write apps for iOS and Android by leveraging Xamarin tools, especially if you've been following this column. It's also well documented that you can take a lot of that C# over to other platforms such as Windows Phone and Windows Store, but did you know you can use F#, Visual Basic, Razor, HTML, and JavaScript in your apps, as well?

One of the great things about the Microsoft .NET Framework platform is the variety of languages at your disposal, but you don't need to leave that flexibility behind when writing mobile apps. In this article, I'll show how you can combine each of these languages within a single native iOS app, starting with a standard Xamarin.iOS project written in C# as the base, and then bring in each of the other languages to add functionality.

F#
F# has been around for nearly a decade now, but has really been gaining a lot of steam in the last couple years in many areas, especially because it's been extended to a variety of platforms like iOS, Android, Windows Phone, Mac OS X and more. I'll start off by creating a new F# Portable Class Library (PCL) named FSharpLib and add a file named MathHelpers.fs to it:

namespace FSharpLib

type MathHelpers = 
  static member Factorial (num:int): int64 =
    match num with
    | 1 -> int64(1)
    | num -> int64(num) * MathHelpers.Factorial(num - 1)

One of the nicest features of F# is its powerful type system, which makes it a great fit for subjects that rely heavily on units of measure, such as math and physics. It's often said that once your code satisfies the type system and compiles, it's very likely it will work correctly.

F# code also tends to be quite succinct, allowing developers to express solutions succinctly, resulting in simple, maintainable code. Writing a factorial function like my example wouldn't result in many lines in any language, but the result is readable and easy to understand.

With the class library in place, I can now add a reference to it from the iOS app and start using it from C#. For the UI, I'll create a simple screen with a textbox for taking in a number, a label for displaying the resulting factorial and a button to trigger the calculation, as shown in Figure 1.

[Click on image for larger view.] Figure 1. A simple screen written in C# that calls into F# code to perform calculations

With that in place, I can use it from the view controller, written in C# (see Listing 1).

Listing 1: The C# View Controller
using System;
using MonoTouch.UIKit;
using FSharpLib;

namespace MultiLanguageDemo
{
  partial class FSharpViewController : UIViewController
  {
    public FSharpViewController (IntPtr handle) : base (handle)
    {
    }

    partial void Calculate_TouchUpInside(UIButton sender)
    {
      if (string.IsNullOrWhiteSpace(Number.Text))
        return;

      Answer.Text = MathHelpers.Factorial(int.Parse(Number.Text)).ToString();
    }
  }
}

Because FSharpLib is a portable class library it can be used directly from C# code the same way you would with a C# library. Xamarin also supports F# as a first class language for iOS and Android, so you can actually write your entire app in F# if you want to!

Visual Basic
I actually swore off writing Visual Basic years ago, but for you, dear reader, I'll make an exception. Once again taking advantage of PCLs, I'll create one named VisualBasicLib and add a class named UserRepository, as shown in Listing 2.

Listing 2: Adding the UserRepository Class to VisualBasicLib
Option Strict On

Public Class UserRepository
  Private _users As XElement =
  <users>
    <user>Greg Shackles</user>
    <user>Wallace McClure</user>
  </users>

  Public Function ListUsers() As IEnumerable(Of String)
    Return From user In _users...<user>
       Select user.Value
  End Function
End Class

In this class I take advantage of the powerful XML functionality in Visual Basic, providing a method that queries from XML and returns a collection of users contained in it. For the UI, I'll keep it simple and display the list in a single label, putting a new line in between each item (see Listing 3).

Listing 3: Single Label List with a Line in Between Each Item
using System;
using MonoTouch.UIKit;
using VisualBasicLib;

namespace MultiLanguageDemo
{
  partial class VBViewController : UIViewController
  {
    private readonly UserRepository _repository = new UserRepository();

    public VBViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad()
    {
      base.ViewDidLoad();

      UserList.Text = string.Join(Environment.NewLine, _repository.ListUsers());
    }
  }
}

The result is Figure 2.

[Click on image for larger view.] Figure 2. Another simple screen written in C# that calls Visual Basic code to query XML and display a list of results

Razor, HTML and JavaScript
If you've used ASP.NET before you're probably already familiar with the Razor templating engine. Even though it's typically associated with ASP.NET applications, the Razor engine can actually be used independently of it, as well.

One of the main selling points of Xamarin is it provides a fully native experience, which is true, but something that often goes overlooked is that it also provides a great hybrid app experience. Xamarin provides a preprocessed Razor item template type that you can use in your apps, allowing you to weave in Web views wherever they make sense in your apps, giving you the best of both worlds, as shown in Figure 3. Because the template is pre-processed, it generates C# code and, therefore, can be shared across multiple platforms, making it even more powerful.

[Click on image for larger view.] Figure 3. Xamarin offers a pre-processed Razor item template that allows you to use Web views wherever you need them.

Just like in ASP.NET apps, Razor templates can accept a model type to keep things strongly typed. For this example, I'll define a simple model that stores data for a person, including their name, job title and a list of interests:

using System.Collections.Generic;

namespace MultiLanguageDemo.Web
{
  public class PersonModel
  {
    public string Name { get; set; }
    public string Title { get; set; }
    public string Company { get; set; }
    public IList<string> Interests { get; set; }
  }
}

With the model defined, I can create a simple Razor view that will display the data, as shown in Listing 4.

Listing 4: Razor View to Display the Data
@model MultiLanguageDemo.Web.PersonModel

<html>
  <head>
    <style type="text/css">
      body {
        color: #c92727;
        font-family: HelveticaNeue-Bold;
      }
    </style>
  </head>
  <body>
    <h1>@Model.Name</h1>
            
    <p>
      <em>@Model.Title</em><br />
      <strong>@Model.Company</strong>
    </p>
            
    <h3>Interests:</h3>
    <ul>
      @foreach (var interest in Model.Interests) {
        <li>@interest</li>
      }
    </ul>
  </body>
</html>

Because the HTML will be loaded into a Web view on the target platform, you can take advantage of anything you'd normally use on the client-side of a site like JavaScript and CSS. You can even bring in your favorite libraries for both, such as jQuery or Bootstrap.

The pre-processed template will generate a C# class named Person that exposes a GenerateString method to produce the HTML for the view, which can then be supplied to the Web view, as shown in Listing 5.

Listing 5: Rendering the Razor template into a Web View
using System;
using System.Collections.Generic;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MultiLanguageDemo.Web;

namespace MultiLanguageDemo
{
  partial class RazorViewController : UIViewController
  {
    public RazorViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad()
    {
      base.ViewDidLoad();

      var person = new PersonModel
      {
        Name = "Greg Shackles",
        Title = "Senior Engineer",
        Company = "Olo",
        Interests = new List<string>
        {
          "Mobile development",
          "Heavy metal",
          "Homebrewing"
        }
      };
      var html = (new Person {Model = person}).GenerateString();

      WebView.LoadHtmlString(html, NSBundle.MainBundle.BundleUrl);
    }
  }
}

The resulting view will look like Figure 4.

[Click on image for larger view.] Figure 4. A Web view displaying the output of a Razor template that was given a C# model

The fun doesn't stop there, though! It's actually possible to communicate between your apps and the Web view in both directions using JavaScript. To start off, I'll add a button to the top-right corner of the screen that will pass JavaScript code into the view, which will then execute immediately:

NavigationItem.RightBarButtonItem = 
  new UIBarButtonItem(UIBarButtonSystemItem.Play,
    (sender, args) => 
      WebView.EvaluateJavascript("alert('Hello from C# land!');"));

When the button is tapped it will raise an alert box through the Web view, which is showin in Figure 5. This is a trivial example, but you can execute any JavaScript you want this way.

[Click on image for larger view.] Figure 5. Displaying an alert in JavaScript that was triggered from C# code

In addition to being able to use JavaScript to talk from C# to the Web view, you can also communicate from the Web view back to your application by navigating. To start, I'll update the Web view to customize how navigations are handled:

WebView.ShouldStartLoad += (view, request, type) =>
{
  if (!request.Url.ToString().StartsWith("myapp://pidgin"))
    return true;

  new UIAlertView("Message from JavaScript", request.Url.Query, null, "Ok", null).Show();

  return false;
};

When a navigation occurs, this method will be invoked. If the new URL matches the predefined scheme, it will cancel the navigation and execute code based on the data provided in the URL. If the URL doesn't match, the Web view is allowed to process it normally.

Finally, I just need to add some code to the Razor template to trigger this navigation. Just like in normal Web development, this can be done through standard links, but it can also be triggered through JavaScript to enable more complicated scenarios:

<p>
  <a href="#" id="TalkToCSharp">Say hello to C#</a>
</p>
    
<script>
  (function() {
    document.getElementById("TalkToCSharp").addEventListener("click", function () {
      window.location = "myapp://pidgin?hello";
    }, false);
  })();
</script>

When the link is tapped, an alert box is showed through C# in the view controller, displaying the query string sent with the URL, as shown in Figure 6.

[Click on image for larger view.] Figure 6. Displaying an alert in C# code that was triggered from JavaScript

This only scratches the surface of what you can do with Web views in an app, as you can leverage the full power of the Web where it makes sense in your apps. It's also worth noting that you aren't limited to views that take up the entire screen. You can mix Web views into your app any way you like, such as for individual items in a native list.

Wrapping Up
As demonstrated here, there's a wide variety of languages available to you when building mobile apps. You can easily weave them together within a single app to take full advantage of each where they make sense. It also means that you can bring in existing code you have in any of these languages and leverage them in ways and platforms you might not even have thought of when you first wrote it!

About the Author

Greg Shackles, Microsoft MVP, Xamarin MVP, is a Principal Engineer at Olo. He hosts the Gone Mobile podcast, organizes the NYC Mobile .NET Developers Group, and wrote Mobile Development with C# (O'Reilly). Greg is obsessed with heavy metal, baseball, and craft beer (he’s an aspiring home brewer). Contact him at Twitter @gshackles.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube