What you will learn
- Explain Model–View–ViewModel
- Bind Entry and Label controls to ViewModel properties
- Execute a ViewModel command without a Clicked event handler
MauiMvvm with .NET 10. Use the complete file listings below, and leave other template-generated files unchanged unless the lesson explicitly says otherwise. Run the Android target on Windows.1. Create a project and install the toolkit
Create MauiMvvm using the .NET MAUI App template. Right-click the project, choose Manage NuGet Packages, search for the CommunityToolkit.Mvvm package, install a version compatible with your project, and restore packages. This package is separate from CommunityToolkit.Maui.
2. Create the ViewModel
Add a folder named ViewModels and a C# class named GreetingViewModel.cs. This example uses ObservableObject and SetProperty directly instead of generated partial properties, making the data flow easy to read.
Name is bound two-way to an Entry. Greeting is bound to a Label. GreetCommand is bound to the Button.
3. Connect the view to the ViewModel
Replace the two MainPage files shown below. The constructor sets BindingContext to a new ViewModel instance. When the button executes the command, SetProperty notifies the UI that the greeting has changed.
4. Verify the binding
- Run the project on Android.
- Type a name in the Entry.
- Tap Update greeting.
- Observe that the Label updates even though MainPage has no button-click handler.
Complete sample code
Use the exact file names and folder locations shown below. Copy each listing into your MAUI project. The separate source files can also be downloaded individually.
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace MauiMvvm.ViewModels;
public class GreetingViewModel : ObservableObject
{
private string name = "";
private string greeting = "Enter a name to begin.";
public string Name
{
get => name;
set => SetProperty(ref name, value);
}
public string Greeting
{
get => greeting;
set => SetProperty(ref greeting, value);
}
public IRelayCommand GreetCommand { get; }
public GreetingViewModel()
{
GreetCommand = new RelayCommand(Greet);
}
private void Greet()
{
Greeting = string.IsNullOrWhiteSpace(Name)
? "Hello from MVVM!"
: $"Welcome, {Name.Trim()}!";
}
}<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiMvvm.MainPage"
Title="MVVM Example">
<VerticalStackLayout Padding="24" Spacing="16">
<Label Text="MVVM Greeting" FontSize="26"
FontAttributes="Bold" />
<Entry Placeholder="Your name"
Text="{Binding Name, Mode=TwoWay}" />
<Button Text="Update greeting"
Command="{Binding GreetCommand}" />
<Label Text="{Binding Greeting}" FontSize="20" />
</VerticalStackLayout>
</ContentPage>using MauiMvvm.ViewModels;
namespace MauiMvvm;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new GreetingViewModel();
}
}Common problems and solutions
- Namespace not found for CommunityToolkit: Install the CommunityToolkit.Mvvm NuGet package and restore packages.
- Bindings show empty values: Check BindingContext in MainPage.xaml.cs and property names in the XAML.
Practice exercise
Add an observable Counter property and an IncrementCommand to the ViewModel, then bind them to a label and button.