100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
.NET

MVVM in Xamarin

How MVVM was implemented in Xamarin.Forms using MVVM Light or CommunityToolkit.Mvvm-era libraries, INotifyPropertyChanged, Command, and the MessagingCenter, and how it maps to MAUI's evolution.

MVVM FrameworksIntermediate9 min readJul 10, 2026
Analogies

MVVM Foundations in Xamarin.Forms

Xamarin.Forms (the predecessor to .NET MAUI, officially end-of-life since May 2024) implemented MVVM through the same core interfaces as WPF, INotifyPropertyChanged for observable properties and Xamarin.Forms.Command / Command<T> implementing ICommand, but without built-in source generators, so most teams either hand-wrote SetProperty-style base classes or adopted a library such as MVVM Light, Prism.Forms, or early Microsoft.Toolkit.Mvvm to reduce boilerplate. Data binding was configured via {Binding PropertyName} in XAML with BindingContext typically set either in code-behind (BindingContext = new MainViewModel()) or resolved through a DI container registered in the App class, and unlike MAUI's compiled x:DataType bindings, Xamarin.Forms bindings were reflection-based by default unless the opt-in Compiled Bindings feature (added in Xamarin.Forms 3.6) was explicitly enabled.

🏏

Cricket analogy: Like the era before DRS when umpires relied purely on their own eyesight for close calls, Xamarin.Forms relied purely on runtime reflection for bindings by default, until Compiled Bindings later added a technology-assisted, more accurate check similar to how DRS was introduced.

MessagingCenter and Navigation

Xamarin.Forms' built-in MessagingCenter.Send<TSender>(sender, "message") and MessagingCenter.Subscribe<TSender> provided a simple, if now-deprecated, publish-subscribe mechanism for decoupled view-model communication, similar in intent to Prism's IEventAggregator or CommunityToolkit.Mvvm's IMessenger, though it lacked strong typing beyond the message string and required manual Unsubscribe calls to avoid leaks since it did not use weak references by default. Page-to-page navigation was handled through INavigation (via Application.Current.MainPage.Navigation.PushAsync(new DetailPage())), which meant view models often needed either an injected navigation-service abstraction or a reference back to a page to trigger navigation, a pain point that MAUI's Shell-based URI navigation was specifically designed to solve.

🏏

Cricket analogy: Like a stadium announcer's manual paper cue cards for updates before digital scoreboards, requiring someone to remember to remove the card, MessagingCenter required a manual Unsubscribe call to avoid a stale, leaking subscription.

csharp
// Xamarin.Forms-era view model (pre-MAUI, pre-source-generators)
public class LoginViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string username;
    public string Username
    {
        get => username;
        set { username = value; OnPropertyChanged(nameof(Username)); }
    }

    public ICommand LoginCommand { get; }

    public LoginViewModel()
    {
        LoginCommand = new Command(async () => await LoginAsync(), () => !string.IsNullOrEmpty(Username));
    }

    private async Task LoginAsync()
    {
        MessagingCenter.Send(this, "UserLoggedIn");
        await Application.Current.MainPage.Navigation.PushAsync(new HomePage());
    }

    protected void OnPropertyChanged(string name) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

Migrating Xamarin.Forms MVVM to MAUI

Because Xamarin.Forms and .NET MAUI share the same MVVM philosophy, a project's view-model layer, if it already used INotifyPropertyChanged and ICommand cleanly, is usually the most portable part of a migration; Microsoft's own .NET Upgrade Assistant automates namespace changes (Xamarin.Forms to Microsoft.Maui and Microsoft.Maui.Controls) and project-format conversion, but MessagingCenter must be manually replaced with CommunityToolkit.Mvvm's IMessenger (MessagingCenter is marked obsolete in MAUI and removed in newer MAUI versions), and PushAsync-based navigation is typically replatformed onto Shell's GoToAsync for maintainability, even though INavigation.PushAsync still technically works in MAUI without Shell.

🏏

Cricket analogy: Like a player transferring from a domestic T20 league to the IPL keeping the same batting technique but adapting to a new franchise's support staff and facilities, a Xamarin.Forms view model keeps its INotifyPropertyChanged logic but adapts to MAUI's new services like IMessenger.

Xamarin.Forms reached end of support on May 1, 2024; any app still targeting it receives no further security patches or OS compatibility updates, so new MVVM work should target .NET MAUI directly, and existing Xamarin.Forms apps should be prioritized for migration rather than continued feature development.

  • Xamarin.Forms used the same INotifyPropertyChanged and ICommand foundations as WPF, but without built-in source generators.
  • Compiled Bindings, added in Xamarin.Forms 3.6, were opt-in, unlike MAUI where x:DataType compiled bindings are the recommended default.
  • MessagingCenter provided basic pub-sub messaging but required manual Unsubscribe calls and lacked strong typing.
  • Navigation relied on INavigation.PushAsync, typically requiring view models to hold or be given navigation capability.
  • Xamarin.Forms reached end of support on May 1, 2024, making migration to MAUI a priority for existing apps.
  • MessagingCenter is obsolete in MAUI; CommunityToolkit.Mvvm's IMessenger is the recommended replacement.
  • The view-model layer is typically the most portable part of a Xamarin.Forms-to-MAUI migration if MVVM was implemented cleanly.

Practice what you learned

Was this page helpful?

Topics covered

#NET#MVVMDesignPatternStudyNotes#MicrosoftTechnologies#MVVMInXamarin#MVVM#Xamarin#Foundations#Forms#StudyNotes#SkillVeris