Our beloved Xamarin was sunset a while ago, and MAUI is now stable enough to start building production apps with it. As you may know from my blog’s history, I’ve been a long-time mobile developer, who’s worked with Xamarin, Flutter, MAUI, and I built this Xamarin.Forms chat app 5 years ago to showcase how to use Xamarin to build a real-world beautiful chat app. Then I migrated it to MAUI for the community to benefit from it. In this article, I’ll show you the main things you need to know when migrating from Xamarin to MAUI. I’ll go through the tips, the pitfalls of building the cross-platform UI, native UI modifications, and the ViewModel. Microsoft did a good job of making MAUI close enough to Xamarin, but as you’ll see, a few things are still missing.

The app we’ll be migrating from Xamarin to MAUI “FreeChat”

FreeChat is a beautiful demo chat app that allows you to chat with your peers. Kind of WhatsApp. There is no back-end code, and only the UI components have been built. The chat is simulated in the app’s logic layer. The first version was fully in Xamaring Forms, with UI tricks, Native UIs etc then I migrated to MAUI Here’s what it looks like:

1 – The Hostbuilder pattern

The first thing I do when I start a new App is to set up the foundations. That is, the services, the initial database layer, Logging, etc, and all these will be used by the ViewModels, and a dependency injection layer is necessary. In Xamarin.Forms, this layer used to be the “AppLocator” and every dev used to do things his own way. But MAUI came in with an opinionated way of registering all of these services, handlers, and more. This pattern is inspired by ASP.NET Core’s HostBuilder, and is very practical.

This is the easiest part of the migration process. All you need to do is import your C# code, and register your services appropriately. But there are a few things you must take into consideration when registering the services.

💼 Need Help with Xamarin, .NET MAUI, Flutter, or ASP.NET Core?

I’m Damien Doumer, a freelance developer, 3x Microsoft MVP, with years of experience building and migrating cross-platform mobile apps and modern web APIs. Whether you’re maintaining a legacy Xamarin project, planning a full migration to MAUI, or building something new with Flutter or ASP.NET Core — I can help.

✔️ Xamarin to .NET MAUI or Flutter migrations
✔️ Cross-platform UI/UX design (XAML, Flutter)
✔️ Performance tuning & architecture
✔️ Backend/API development with ASP.NET Core

📩 Let’s talk! I’m available for freelance and contract work.
📧 Reach out at damien@doumer.me

Let’s build something great together.

Follow me on social media and stay updated

Service LifeSpan

If you’re an ASP.NET Core dev, this should be obvious. But if you aren’t, note that the way you register your services is very important! This pattern, gotten from a server-side architecture, is not always suitable for mobile apps. Mobile apps have limited resources (in this case, memory, especially).

  • Transient lifespan: The service or class registered will have a new instance created anytime you call it
  • Scoped: One instance will be created per navigation scope
  • Singleton: One instance of the service will be created for the entire app.

Registering Singletons is better for HttpClients, data access services etc… for performance issues. If you want to know why, check out this article I wrote about performance in you MAUI/Xamarin Apps. In the example above, I registered the MessagesPage as transient because I do a modal navigation on it, and for every new conversation the user clicks on, the messages loaded will be unique.

Registering Components, Handlers, Fonts and More

The hostbuilder pattern isn’t only useful for services. If you had your Xamarin app with custom fonts, no need for the crazy gymnastics we used to do in Xamarin. Just register them by pasting them in the resources folder and placing their names in the MAUI program with the HostBuilder pattern.

2 – The UI (XAML), UI Plugins and the UI

I’ve always used XAML to build my UIs, and what I find awesome here is that almost nothing is required for you to do for your Xamarin XAML to work in MAUI.

Less need for third-party UI libraries (Example: Pancake view to border)

To add borders, gradients, and shadows to your controls, the pancake view plugin was the most popular plugin to do so in Xamarin. We don’t need it anymore, so you can use the border instead of it.

  • Native performance: Border is a native control, eliminating custom renderer overhead
  • Simplified syntax: StrokeShape="RoundRectangle 18" is more intuitive than separate CornerRadius properties
  • Consistent shadows: Native shadow support works uniformly across platforms
  • No external dependencies: Reduces package bloat and maintenance overhead
  • Single control: Replaces multiple PancakeView elements with one clean Border

XAML Strict Type Safety

Type safety in XAML was made more rigid in MAUI. In Xamarin.Forms, you could add type safety, but the compiler would let you access properties from objects other than those of the current binding context. This is no longer possible in MAUI’s XAML. I guess the Microsoft MAUI team decided to do that to enhance performance. Check the example below, where I could reference the parent’s page BindingContext’s Command. In MAUI, you can’t compile that same code if you set the x:DataType of the view.

Handlers instead of Renderers and Effects

In Xamarin Forms, when you needed to build a custom native control, or modify an existing one, you had to do a lot of boilerplate code with either renderers, or effects. For example, in the Xamarin.Forms project, I needed to make an Editor and Entry controls borderless. This was tedious, with code in every specific platform, etc. In MAUI, you write once and register the handler in the host builder, then instantiate the custom control in XAML.

Shell Modal Navigation not available in MAUI

Difficult for me to say if this is a bug or a feature. There’s no obvious reason why Shell’s modal animated isn’t working in MAUI, despite all the configurations and options being available in MAUI. I had to call raw modal navigation despite the app using Shell. For example, setting a page as modal and adding these configurations won’t work.

To have real modal navigation as we used to have in Xamarin Forms, I had to do it the old way.

CollectionView Performance

The most disappointing surprise I had the first time I tried MAUI a few years ago, was the CollectionView’s performance. They weren’t good in Xamarin, and they seem to be worse in MAUI. I have done a benchmark, but it is not good from my experience, and I’d recommend using Bindable layouts, and a simple listview when possible. The CollectionView can sometimes be laggy.

3 – The ViewModels

MAUI Community Toolkit MVVM is truly a game changer. You no longer need an external MVVM library when building your apps. The ease with which you implement the MVVM design pattern is amazing. In the Xamarin.Forms project, I used ReactiveUI for MVVM (a niche MVVM library that leverages Reactive Programming), but in the example below, I’ll show you how things were done without any MVVM library, and how to move them to MAUI.

The [ObservableProperty] attribute generates the complete property implementation at compile time, including:

  • Public property with proper naming (removes underscore prefix and capitalizes)
  • INotifyPropertyChanged implementation
  • Automatic change detection and notification
  • Thread-safe property updates

All you need when implementing a command is the method that does the processing. Source generators will automatically handle the rest for you.

  • Automatic ICommand property generation (FilterOptionChangedCommand)
  • Built-in async support with proper exception handling
  • Declarative CanExecute binding with automatic refresh
  • Type-safe parameter handling
  • Reduced boilerplate code by 70-80%

Conclusion

You see how easy it is to migrate from Xamarin.Forms to MAUI ? I hope you liked it. In case you did, please don’t hesitate to share this article and leave a star on my Github repository. And if you need help for Xamarin/MAUI/Flutter or ASP.net core, don’t hesitate to contact me. I work as a freelancer, and will be glad to help (damien@doumer.me).

Follow me on social media and stay updated

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.