LightUpMacXamarinForms_870x220

We explore the potential of building native MacOS apps with Xamarin.Forms and Telerik UI.

The promise of Xamarin.Forms has been undeniable for developers - write apps in C#/XAML and reach a variety of platforms. Xamarin democratizes mobile development for .NET developers with two huge wins - reuse existing skills and build apps for popular mobile platforms. And you can light up your Xamarin mobile apps with polished performant UI controls with Telerik UI for Xamarin - you should try it.

But mobile isn't everything, Could Xamarin.Form's reach be stretched to other platforms? Turns out, the world can be an oyster for .NET developers and lots of efforts are underway to substantially increase Xamarin.Form's potential across platforms. This article explores the possibilities for native MacOS apps through Xamarin.Forms - yup, Mac apps written in C#/XAML with no platform-specific code!

Xamarin.Forms Heads

With traditional Xamarin, we were able to abstract out app business logic into a C# layer - this was a big step in the right direction, but needed developers to build the UI for each supporting platform separately. While this approach (called Xamarin.iOS or Xamarin.Android) is a legit strategy for native platform-specific apps, it needs .NET developers to know the details on how to build iOS/Android UI - this is uncomfortable zone for many.

Enter Xamarin.Forms - offering .NET developers an UI abstraction layer. Developers now get to write XAML in a shared UI layer - at runtime, Xamarin.Forms turns around to render native UI for each platform. Hallelujah!

XFHeads

The platforms that Xamarin.Forms supports are often referred to as Heads. And the magic of turning generic XAML into native UI for each platform is done by the Renderers - there are renderers for each Xamarin.Forms UI abstraction which do the heavy lifting to render appropriate UI for corresponding platforms.

So could Xamarin.Forms have more heads? Sure thing - just add more renderers for newer platforms that need to be supported. The reality is a little more complicated, but the good news is that some very sharp minds are working on taking Xamarin.Forms places. Efforts are underway to take Xamarin.Forms support to several new platforms - like MacOS, GTK LinuxWPFSamsung Tizen and even Web. The story of Xamarin.Forms' reach is about to get a whole lot better!

NewXFHeads

The MacOS Project

Since Xamarin.Forms 2.3.5 Pre-Release, MacOS support through Xamarin.Forms is in Preview. It is pretty magical to think that developers can now build truly native Mac apps with only a few tweaks in Xamarin.Forms - and with minimal platform specific code. Let's take a look as to how we add MacOS support in an existing Xamarin.Forms solution - this is the future.

First, MacOS support is obviously a Mac-only feature - no other way to run native Mac apps. Granted you are in Visual Studio for Mac and have an existing Xamarin.Forms solution, the first step is to add a MacOS project. Until MacOS support is official, Xamarin.Forms will not have VS project templates. It's easy to get around this by adding a Mac (Cocoa app) to your Xamarin.Forms solution, like below. This is similar to what you may do if building Xamarin.Mac apps with C# - except that instead of Storyboards, we'll use Xamarin.Forms to render the UI.

NewMacProject

Next up, give your Mac project a name and choose MacOS target version. For consistency with rest of Xamarin.Form projects, you may want to name your project ending in .MacOS - of course, the app name can be different when displayed in the Mac dock.

ConfigureMacProject

Once added, your MacOS project should look no different from the other Xamarin.Forms projects. So your solution would have a shared PCL or .NET Standard project, and platform specific projects for iOS, Android, UWP and now MacOS.

XFMacProject

Now there are few things you need to do to set up your MacOS project - you essentially want to the Xamarin.Forms rendering engine to bootstrap and drive the Mac app UI.

First, the Cocoa App template is configured with a storyboard implementation that you don’t need - open up the info.plist file and remove the NSMainStoryboardFile source entry. Next, you'll want to add the Xamarin.Forms reference as a NuGet package. There's ongoing work in the pre-release versions... as of this writing, 2.4.0.282 is the last version that seems to have everything functional. You'll want NuGet UI to show you pre-release versions of packages or simply add a direct reference through Package Manager Console. Then, to inject Xamarin.Forms UI and shared code, you'll want to add a reference in your MacOS project back to the shared PCL or .NET Standard library.

The Mac app uses Main.cs as the initial entry point - let us initialize the use of AppDelegate.

using AppKit;
 
namespace XamarinFormsEveryWhere.MacOS
{
    static class MainClass
    {
        static void Main(string[] args)
        {
            NSApplication.Init();
            NSApplication.SharedApplication.Delegate = new AppDelegate();
            NSApplication.Main(args);
        }
    }
}

It's Showtime

So far, nothing has been done that is MacOS platform-specific - but the next step is. However, this is only in the Mac app's AppDelegate file - one time only and just to new up the frame for the Mac app.

using AppKit;
using Foundation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.MacOS;
using XamarinFormsEverywhere;
 
namespace XamarinFormsEveryWhere.MacOS
{
    [Register("AppDelegate")]
    public class AppDelegate : FormsApplicationDelegate
    {
        NSWindow _window;
 
        public AppDelegate()
        {
            var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
 
            var rect = new CoreGraphics.CGRect(500, 1000, 500, 500);
            _window = new NSWindow(rect, style, NSBackingStore.Buffered, false);
            _window.Title = "Xamarin.Forms on Mac!";
            _window.TitleVisibility = NSWindowTitleVisibility.Hidden;
        }
 
        public override NSWindow MainWindow
        {
            get { return _window; }
        }
 
        public override void DidFinishLaunching(NSNotification notification)
        {
            Forms.Init();
            LoadApplication(new App());
            base.DidFinishLaunching(notification);
        }
 
        public override void WillTerminate(NSNotification notification)
        {
            // Insert code here to tear down your application
        }
    }
}

While most of the code is self-explanatory, a couple of core pieces work to bootstrap the Mac app. Notice how the AppDelegate inherits off FormsApplicationDelegate - this is a construct from Xamarin.Form's MacOS support with a few overrides that allow injecting Xamarin content within a custom Mac app window. NSWindow is the Mac app frame and CoreGraphics is being used to create the rectangle for the window. Notice this line of code - new CoreGraphics.CGRect(500, 1000, 500, 500) - those are the X/Y coordinates and the initial width/height of the window. Add some custom styling - and you really get to control the initial app window experience. Override the MainWindow method to return the NSWindow that was set up and new up the Xamarin.Forms app in DidFinishLaunching() - that's about it.

You can see most of this code is boilerplate - and it's the only thing you really need to do in the MacOS project. All of your app's UI and business logic code can happily reside in the shared Xamarin.Forms project. Xamarin.Forms code in a shared project simply points to a start page with minimal XAML, like so:

// App.xaml.cs
public App()
{
    InitializeComponent();
    MainPage = new XamarinFormsEverywherePage();
}
// XamarinFormsEverywherePage 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:local="clr-namespace:XamarinFormsEverywhere" x:Class="XamarinFormsEverywhere.XamarinFormsEverywherePage">
    <Label Text="Welcome to Xamarin Forms!" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

If all is in place, dare we hit F5 to run our app? These are all preview bits - so the worst that can happen is your Mac going up in flames. Thankfully, you should have a voila moment - a native Mac app showing Xamarin.Forms UI in your custom window. Your Mac app should run like any other desktop app with Dock support.

XFMacApp

MacApponDock

Telerik UI

So now that you can build MacOS apps with Xamarin.Forms, the next frontier should be - building beautiful MacOS apps. Keep in mind, MacOS support through Xamarin.Forms is very much a Preview - with several known UI issues. However, most generic Xamarin.Forms UI controls should work as is in Mac apps. While you can reuse XAML from PCL project views, one consideration to keep in mind is the additional real estate of Mac apps compared to mobile form factors. App UI is likely going to need rethinking, now that the target platform is Mac desktop.

Out of the box Xamarin.Forms controls only go so far though, when trying to build gorgeous app UI. Developers often augment their development arsenal to fill the UI gaps - and pick up well-engineered polished UI controls for Xamarin.Forms apps. To that end, Telerik UI for Xamarin is here to help you build fluid UX through UI controls that are too hard to create from scratch. Telerik UI for Xamarin provides performant native UI widgets for all your Xamarin apps - Xamarin.iOS, Xamarin.Android and of course, Xamarin.Forms.

Go ahead, give it a try by downloading the bits in a free trial today.

Download Telerik UI for Xamarin

So now that Xamarin.Forms apps can target MacOS, your obvious curiosity may be - can I use Telerik UI for Xamarin controls in my Mac apps? The answer is yes and no. First up, slow down and realize that MacOS support for Xamarin.Forms will be in Preview for a while - these are hot bits we're playing with that can make compatibility fragile. And there are NuGet dependencies that just don't work in MacOS world until things are straightened out. But the promise is there.

To get started, first thing we need to do is add Telerik UI for Xamarin references to our Mac project - hopefully, you already have this for your other Xamarin.Forms projects. While you can do things manually, pulling in Telerik UI for Xamarin bits into an existing project is best done through the NuGet route. You can bring in the bits from the Telerik NuGet server - simply set it up as a NuGet source with your credentials.

TelerikNuGetSource

Next, look for Telerik UI for Xamarin NuGet package - one click and done. You now have all the references you need to light up your Xamarin apps with any of the included Telerik UI controls. Keep in mind, however, that this is the Master package and most times, an overkill. There are several variations of light-weight NuGet packages than you can pull in Telerik UI for Xamarin bits as - based on which exact UI controls you actually use in your app.

TelerikNugetPackage

Once all the Xamarin.Forms and Telerik bits are in place, here is a glimpse of how the references may look for your MacOS project.

MacAppRefs

So do the Telerik UI for Xamarin bits work in a Mac app? Some do, most don't. Keep in mind these are very early bits we're playing with. Any UI requiring SkiaSharp library does not seem to be functional for Mac apps yet - these missing pieces will fall in place once MacOS support gets close to official.

Here's a quick example of throwing in some Telerik UI for Xamarin controls for our Mac app - in particular, the Button and SlideView controls. Note that this is being done in the Xamarin.Forms PCL project as a stand-alone view - no code needed in the MacOS project.

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="XamarinFormsEverywhere.TelerikUI"
             xmlns:telerikPrimitives="clr-namespace:Telerik.XamarinForms.Primitives;assembly=Telerik.XamarinForms.Primitives"
             xmlns:telerikInput="clr-namespace:Telerik.XamarinForms.Input;assembly=Telerik.XamarinForms.Input">
    <ContentPage.Content>
        <StackLayout Orientation="Vertical" VerticalOptions="Center">
            <telerikInput:RadButton x:Name="button" Text="I'm a Telerik Button!" BorderThickness="2" BorderColor="#4488F6"
                                    HorizontalContentAlignment="Center" VerticalContentAlignment="Center" WidthRequest="200" HeightRequest="60"/>
            <telerikPrimitives:RadSlideView>
                <telerikPrimitives:RadSlideView.ItemsSource>
                    <x:Array Type="{x:Type x:String}">                   
                        <x:String>1</x:String>
                        <x:String>2</x:String>
                        <x:String>3</x:String>
                    </x:Array>
                </telerikPrimitives:RadSlideView.ItemsSource>
            </telerikPrimitives:RadSlideView>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

There is no data binding or code behind behaviors - simply a test to see if Telerik UI for Xamarin controls light up in a Mac app. Fire it up and sure enough - nerd nirvana! I don't win the remotest cookie points for good UI, but the proof of concept proves the promise is there.

TelerikUIinMac

So few of the Telerik UI for Xamarin bits do work unofficially in an unofficial MacOS Preview for Xamarin.Forms. What does this mean then - nothing more than geekiness to push the envelope. Rest assured, once Xamarin.Forms officially supports MacOS as a platform, we'll explore how viable Telerik UI for Xamarin controls would be for Mac apps. But you clearly see the promise - wouldn't it be cool to light up your Mac apps with polished Telerik UI?

Extend Your Reach

Xamarin.Forms is awesome - it enables .NET developers to take their apps to hitherto unreachable platforms. C#/XAML can light up apps for Mobile/Tablet platforms and even Augmented/Mixed Reality. And with the upcoming support for MacOS and Linux, Xamarin.Forms should be able to reach all Desktop platforms as well. And Telerik UI for Xamarin will continue to evolve to provide polished UI for all you .NET ninjas. Keep dreaming the dream with Xamarin.Forms - the reality keeps getting better. 

StateOfNet

PS: Want a headstart on where .NET is heading in 2018? Want to know how Xamarin is evolving? How does .NET Standard affect how developers share .NET code across platforms? All this and more is captured in our honest whitepaper - State of .NET. Grab it in your preferred format and give it a read over your next cup of latte. Steaming innovation keeping .NET cool for developers - enjoy!

Read More: The State of .NET in 2018


Sam Basu
About the Author

Sam Basu

Sam Basu is a technologist, author, speaker, Microsoft MVP, gadget-lover and Progress Developer Advocate for Telerik products. With a long developer background, he now spends much of his time advocating modern web/mobile/cloud development platforms on Microsoft/Telerik technology stacks. His spare times call for travel, fast cars, cricket and culinary adventures with the family. You can find him on the internet.

Related Posts

Comments

Comments are disabled in preview mode.