Data Binding in .NET MAUI MVVM

Data binding is a core concept in the Model-View-ViewModel (MVVM) architectural pattern. It establishes a connection between properties of your ViewModels and the UI elements in your Views, allowing for automatic synchronization of data. This tutorial will guide you through the fundamentals of data binding in .NET MAUI.

What is Data Binding?

Data binding is a mechanism that connects two objects, such as a ViewModel property and a UI element property, so that they can communicate. When one property changes, the other is automatically updated. This significantly reduces boilerplate code for updating the UI manually.

In .NET MAUI, data binding is declarative and is typically defined in XAML.

Binding Modes

Data binding supports various modes to control the direction and timing of data synchronization:

Basic Data Binding

The most common scenario is binding a UI element's property to a property in your ViewModel. Let's say you have a ViewModel with a Message property and you want to display it in a Label.

ViewModel Code (Example)


public class MainViewModel : INotifyPropertyChanged
{
    private string _message;
    public string Message
    {
        get => _message;
        set
        {
            if (_message != value)
            {
                _message = value;
                OnPropertyChanged(nameof(Message));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public MainViewModel()
    {
        Message = "Hello from MVVM!";
    }
}
            

XAML View Code (Example)


<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:viewmodels="clr-namespace:YourApp.ViewModels"
             x:Class="YourApp.Views.MainPage">

    <ContentPage.BindingContext>
        <viewmodels:MainViewModel />
    </ContentPage.BindingContext>

    <StackLayout VerticalOptions="Center" HorizontalOptions="Center">
        <Label Text="{Binding Message}" />
    </StackLayout>
</ContentPage>
            

In this example:

Two-Way Binding

Two-way binding is useful when you want user input in a UI element (like an Entry) to update a ViewModel property, and vice-versa.

XAML View Code (Example)


<!-- ... inside your StackLayout ... -->
<Entry Text="{Binding UserName, Mode=TwoWay}" Placeholder="Enter your name" />
<Label Text="Welcome, {Binding UserName}!" />
<!-- ... -->
            

Here, the Entry's Text property is bound to the UserName property of the ViewModel using Mode=TwoWay. Any text entered into the Entry will update the UserName property, and if the UserName property is changed programmatically, the Entry's text will also update.

Binding to Collections

Data binding is also used to display lists of data. You'll typically bind a CollectionView or ListView to an ObservableCollection in your ViewModel.

ViewModel Code (Example)


public class ItemViewModel : INotifyPropertyChanged
{
    public string Name { get; set; }
    // ... other properties
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }
}

public class ListViewModel : INotifyPropertyChanged
{
    private ObservableCollection<ItemViewModel> _items;
    public ObservableCollection<ItemViewModel> Items
    {
        get => _items;
        set
        {
            if (_items != value)
            {
                _items = value;
                OnPropertyChanged(nameof(Items));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); }

    public ListViewModel()
    {
        Items = new ObservableCollection<ItemViewModel>
        {
            new ItemViewModel { Name = "Apple" },
            new ItemViewModel { Name = "Banana" },
            new ItemViewModel { Name = "Cherry" }
        };
    }
}
            

XAML View Code (Example)


<!-- ... inside your page content ... -->
<CollectionView ItemsSource="{Binding Items}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Label Text="{Binding Name}" Padding="10" />
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>
<!-- ... -->
            

The CollectionView's ItemsSource is bound to the Items ObservableCollection. The ItemTemplate defines how each item in the collection is displayed, binding to properties of the ItemViewModel.

Common Binding Issues & Tips

Tip: Ensure your ViewModel implements INotifyPropertyChanged and that you correctly call OnPropertyChanged whenever a bound property's value changes.

Null References

If a binding results in a null reference exception, double-check:

Binding Converters

Sometimes you need to transform data before it's displayed or sent back to the ViewModel. Binding converters allow you to do this. For example, converting a boolean to a string representation or formatting a date.

Example: Using a Boolean to String Converter

ViewModel:


public bool IsActive { get; set; } = true;
                

Converter (Conceptual):


public class BooleanToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool boolValue)
        {
            return boolValue ? "Active" : "Inactive";
        }
        return "N/A";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string stringValue)
        {
            return stringValue.Equals("Active", StringComparison.OrdinalIgnoreCase);
        }
        return false;
    }
}
                

XAML (with converter registered and applied):


<!-- In your ResourceDictionary or Page.Resources -->
<local:BooleanToStringConverter x:Key="BoolConverter" />

<!-- In your UI -->
<Label Text="{Binding IsActive, Converter={StaticResource BoolConverter}}" />
                

Conclusion

Data binding is a powerful feature in .NET MAUI that, when used with the MVVM pattern, leads to cleaner, more maintainable, and testable applications. By understanding binding modes, collection binding, and converters, you can effectively manage data flow between your UI and your ViewModels.