Microsoft announced more than a year ago its new framework for building cross-platform modern applications on mobile and desktop. They called it MAUI. We are not talking about the Maui beach here :-), MAUI actually stands for Multi-platform App UI. This framework is Xamarin.Forms’ evolution. This framework brings several features to make it extremely easy to build robust and real-world modern applications.
As of the time of writing this article, .NET MAUI does not yet have a production-ready stable release, but its preview releases are quite promising. in this post, we will learn what MAUI really is, and we are going to dive into what .NET MAUI has to offer to us, mobile devs hungry for productive ways to build real-world killer apps! 🔥🔥🔥
What Will We Cover ?
- An introduction to .NET MAUI (What is MAUI)
- 6 Ways in which .NET MAUI makes app developers work far easier and faster
- 5 Reasons why you should choose MAUI over other cross platform frameworks like Flutter, React Native, Native Script etc.
- Upgrading from Xamarin Forms Apps to MAUI
What is MAUI ? Introduction to .NET MAUI
.NET MAUI is the next evolution of Xamarin Forms. MAUI takes the best Xamarin forms had to offer, removes the pain points, introduces a new faster, and easier to use architecture, improves performance, adds new features, and lowers the usability barrier.
.NET MAUI is currently still in implementation, and to check its implementation status, you can regularly go to this page to stay updated.
How MAUI makes app developers work Far easier
As a long-time .NET and Xamarin Forms developer, I’ve gone through what Xamarin had to offer. I’ve been with Xamarin since the days where the tooling was really a nightmare to deal with. You can attest to this by reading my former articles about it 😂. I’ve watched Xamarin Forms evolve from a framework to build basic apps, to a framework for production-ready scenarios. With the numerous ameliorations brought to it (visuals, slim renderers, Shell, etc…) And from what I noticed after watching MAUI’s development, the team behind is building MAUI based on exactly what we, the community wanted Xamarin Forms or any other cross-platform framework to be in an ideal world. I mentioned above that .NET MAUI’s preview releases are promising, and that we will cover what it has to offer to us, devs hungry for fast and productive ways of building killer apps. Well, time to fulfill my promise.
1- Abstracting Repetitive Platform Configurations
As a mobile dev, there are some tasks that I just hate re-doing all the time. For example,
- Adding app fonts
- Determining the App’s Splash screen, the app’s icon,
- Adding images with appropriate sizes to each platform etc…
All these, knowing that each platform (Android, iOS, WinUI…) has its own way of adding images or configuring icons or splash screens to the project. .NET MAUI is built from the ground up to abstract these tasks that mobile devs do repetitively.
How do I leverage these abstractions with MAUI, well it is easy. Inside the csproj file, you can add tags to configure these.
1 2 | <MauiImage Include="Resources\Images\*" /> |
The above tag ends with a wildcard character, stating that every svg, png etc… file in the Images folder should be used as an image. Meaning that the different image sizes needed for the other platforms will be generated automatically based on the images found in this folder.
The approach I’m sure you will prefer will be to just drop your SVG files into the images folder and let MAUI do its magic to abstract scaling, resizing, etc.
NOTE THAT, you can still go to your platform folders and add your images in the appropriate resource folders as you used to do traditionally.
1 2 | <MauiFont Include="Resources\Fonts\*" /> |
The same applies to the “MauiFont” tag. Below, you can easily define your app icon and splash screen directly.
1 2 3 4 5 6 7 | <MauiIcon Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" Color="#081B25" /> <MauiFont Include="Resources\Fonts\*.otf" /> <MauiSplashScreen Include="Resources\appiconfg.svg" Color="#081B25" /> |
2- MAUI Single Project
.NET MAUI allows us to build cross platform apps in one project. This is awesome, since we can do everything in one place and MAUI also abstracts some project specific tasks that where repeated multiple times on each project on former Xamarin Forms apps. These include adding Fonts, Images, App Icons etc. You do that once, and it just automagically works everywhere.
To find your platform files (files specific to each platform targeted by your MAUI app), you will now need to go down to the platforms folder. This folder will contain everything platform specific you used to find in your iOS, Android projects. These includes
- The main activity,
- The resources folders
- The App delegate… and much more.
This is something that has surely been never made before. And the Visual studio team had to build new features into Visual studio to adapt to this single project structure. To target a specific framework for builds, you will need to do so via the drop down on the run button of visual studio.
If you find this article useful, please follow me on Twitter, Github, Linkedin, or like my Facebook page to stay updated.Follow me on social media and stay updated
How does this single project structure work under the hood?
This magical project type is possible thanks to “multi-Targeting” this is a concept that was born a few years ago in the .NET echo system. A few years back, you could see some library maintainers in the community adopt multi-targeting in their Xamarin Libraries. Multi-targeting is the act of targeting several frameworks in your app or library. This is done by modifying the “TargetFrameworks” option of your project, by editing your project in a text editor, then adding the TFM (Target Framework Moniker) of the target framework you wish to add.
These TFMs include (net6.0-android for Android, net6.0-ios for iOS, netstandard2.1 for .NET standards 2.1 etc.) You can find the list of all the TFMs available here. This feature now permits us to add nugget packages to the project for a specific target only and to compile for each listed platform.
3- Customise Everything with Handlers
A MAUI handler is an architectural concept used by .NET MAUI to map cross-platform controls to their native implementation. Handlers are used instead of renderers in .NET MAUI because they offer several advantages. Speed, ease of use, easily customizable etc…
Using handlers to customize your controls is very simple. I won’t cover this in detail here, but you can read this post that will guide you through the basics.
The Handlers Architecture was introduced to provide several advantages including:
- Better performance. No more assembly scanning/reflection, native controls are not wrapped into useless containers (fast renderers are used instead).
- Ease of use. It is easier to customise controls on the spot. We no longer need to write whole classes with boiler plate code just to change a few properties of a control.
- More maintainable code can be achieved, with a better API. Handlers are easier to implement, and with dependency injection and the host builder pattern, we can specify what handler we need for which type on one spot. for example, bellow the code snipet shows how to register a specific handler for a control.
1 2 3 4 5 6 7 8 9 10 11 | public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureMauiHandlers(handlers => { handlers.AddHandler(typeof(MyEntry), typeof(MyEntryHandler)); }); return builder.Build(); } |
To better understand the positive impact that handlers have over the former rendrers of xamarin forms, we need to highlight the drawbacks renderers had. As mentioned by Javier Suarez during his talk at Monkey fest, which you can find here.
- Renderers required assembly scanning, which implied that Xamarin Forms scanned your assemblies and via reflection, registered the appropriate types for your UI components. This was a slow process, and impacted negatively the performance of Xamarin Forms views.
- Accessing platform specific controls from the shared project is difficult with renderers. There are means of accessing platform specific controls via renders, but it wasn’t easy.
- To customize one aspect of a control, you had to write a lot of boiler plate code to do just one thing. for example, if you wanted an entry without borders, you had to know about “Elementchanged”, “ExportRenderer”, Check if the control is null etc… Creating a renderer for it required a lot of code to do just a single thing.
Using Rederers in .NET MAUI
You still can use old renderers in .NET MAUI. It is even easier to use renderers in MAUI than using them in Xamarin Forms. Since you won’t need much effort anymore. If you have a renderer you are willing to port to MAUI, in the AppBuilder, just precise the control type you’ll want to use your renderer for. You can learn more about using your renderers in MAUI from this awesome article. Here is an example.
1 2 3 4 | appBuilder.ConfigureMauiHandlers(handlers => { handlers.AddCompatibilityRenderer(typeof(MyButton), typeof(MyButtonRenderer)); }); |
4- Drawn Controls with Microsoft.Maui.Graphics (Material, FluentUI, Cuppertino)
With MAUI, you can build your UIs with existing controls, (or draw your controls) that look alike on every platform, and that could be themed with Fluent UI, Material UI, etc… Having to code a view and make it look the same on every platform is something that was requested a while ago in Xamarin Forms. The Xamarin team heard our cry and brought to us Visuals. This was a useful remedy to this problem, but it wasn’t sufficient. MAUI takes the concept of painted UI to another level. You can watch Javier Suarez’s presentation on this paradigm here.
As mentioned in the video above by Javier Suarez,
Microsoft.MAUI.Graphics is a cross platform graphics library for iOS, Android, Windows, MacOS, Tizen and Linux writen completely in C# that provides a common API to target multiple abstractions allowing you to share your drawind code between platforms or mix and match graphics implementations within a singular application.
by Javier Suarez,
To understand better how this library will provide you a unified API to draw your controls, and use already drawn controls, here is a diagram showing the APIs abstracted on each platform.
.NET MAUI introduced the Graphics view, which functions as skia’s canvas to draw controls on top. This view will allow us to draw any controls on top and expose events for interactions. Using these drawn controls in your MAUI project can be done easily by just choosing the appropriate handlers (Fluent, Material, Cuppertino) in the Maui app builder.
NOTE THAT, this library is still in the experimental phase and is not yet part of .NET MAUI. It is available on a package that ships apart from MAUI. You can checkout progress for these views on github, and contribute to its evolution.
5- The Host Builder Pattern
This is a design pattern used for scaffolding your entire application in a single entry point, simple, easy to understand, and easy to maintain way. This pattern is widely used in the .NET ecosystem to build several types of applications like Blazor apps or APIs with ASP.net Core. To learn more about the app startup configurations, check this documentation. It helps unify the global configuration of your application. You can configure:
- Your App class
- Fonts
- Services via dependency injection
- Initialize MAUI essentials libs you need etc…
You can configure all the above in one place instead of going to your App delegate or Main Activity to do so. Here is a demonstration of how this pattern is used in the sample Weather 21 app you can find on github.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .ConfigureFonts(fonts => { fonts.AddFont("fa-solid-900.ttf", "FontAwesome"); fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-SemiBold.ttf", "OpenSansSemiBold"); }); builder.ConfigureLifecycleEvents(lifecycle => { #if WINDOWS lifecycle .AddWindows(windows => windows.OnLaunched((app, args) => { var winuiApp = (Microsoft.UI.Xaml.Window)MauiWinUIApplication.Current.Application.Windows[0].Handler!.NativeView!; winuiApp.SetIcon("Platforms/Windows/trayicon.ico"); })); #endif }); var services = builder.Services; #if WINDOWS services.AddSingleton<ITrayService, WinUI.TrayService>(); services.AddSingleton<INotificationService, WinUI.NotificationService>(); #elif MACCATALYST services.AddSingleton<ITrayService, MacCatalyst.TrayService>(); services.AddSingleton<INotificationService, MacCatalyst.NotificationService>(); #endif return builder.Build(); } |
6- Hot Reload Everything
This is one of the coolest and most anticipated features that came with .NET 6. Since MAUI is built on .NET 6, it obviously leverages the hot reload feature .NET 6 offers by default. You now have the possibility to not only build your XAML user interface while your app is running, in addition to that you can modify your C# code too.
NOTE THAT: As mentioned by Dmitry Lyalin in the .NET conf, .NET 6’s hot reload works in a wide variety of scenarios, but it still has some limitations. This hot reload technology is based on the edit and continue capabilities of Visual Studio that powered core CLR (.NET execution engine) edit while running. Therefore, .NET apps using the core CLR directly will benefit the most from this functionality. Meanwhile, .NET applications built on the “Mono framework” (.NET iOS, Android, Blazor WASM) will only support method-body-replacement types of edits.
Why chose MAUI Over Other Cross Platform Frameworks
Since you’ve been reading this post up to this point, you know that .NET MAUI is great. What you surely also know, is that there are several other frameworks that offer a means of building cross-platform apps easily so why choose MAUI instead?
- Some cross platform development frameworks are not fully native, thus you’ll have to build platform specific functionalities in each native platform (iOS, Android …) to access APIs like Camera, Sensors, Connevtivity. Meanwhile we have MAUI essentials that provides everything we need for these out of the box.
- MAUI is built specifically for .NET. This is a great advantage for any .NET dev that once to dive into cross platform app development, and do not want to spend time learning new langauges and new tools. You can do everything with your beloved .NET tools and Visualstudio.
- MAUI supports several platforms as first class citizens these include (Android, iOS, Mac, WinUI, Tizen…) (Linux support is not official yet) while other frameworks like Native script support less platforms.
- With MAUI, you can build for the web by leveraging the power of Blazor mobile bindings. whereas you can’t do that with some of its competitors.
- MAUI supports more than one paradigm for building apps. What I prefer with MAUI is that you can do things more than one way.
- You can build your app page after page, by defining your visual hierarchy yourself as you wish.
- You can build your app using the Shell paradigm to layout all your visual hierarchy and perform route navigation with parameters and objects.
- You can chose to paint your controls and make them identical on every platform, with MAUI Graphics. Just like Flutter.
- You can build your apps the old way, with controls having plain old native look and feel specific to each platform.
Upgrading from Xamarin Forms Apps to MAUI
There is the .NET Upgrade assistant available to help you with the task of upgrading your apps. The .NET upgrade assistant is a CLI tool that was built back when .NET 5 was released. It mainly helped .NET devs port their WPF, WinForms… apps to .NET 5. The MAUI team improved this tool to let us migrate our apps to .NET MAUI.
This will not do 100% of the migration work for you though. You will need to continue the work once it finishes its tasks. Here are a few things this upgrade assistant will do for you:
- Update nugget packages
- Change target frameworks
- It currently works for apps targeting Xamarin.Forms >= 4.8.
- Your app will not be converted to MAUI single project type
- You will need to update your XAML namespaces after an upgrade
You can learn more from the docs.
Conclusion
MAUI has a lot to offer, sooo many goodies, but we will have to wait a little longer to have all these beautiful features in a release candidate build of MAUI. Development is actively going on, and we will have to wait just a few more months though we can get our hands dirty right now. I’ll be publishing more articles about .NET MAUI in the upcoming months. So, stay tuned.
References
https://www.youtube.com/watch?v=M6eFXAz3g3s&list=PLdo4fOcmZ0oVFtp9MDEBNbA2sSqYvXSXO&index=9
Follow me on social media and stay updated