ObservableCollection .NET MAUI

UPDATE UI WITH OBSERVABLECOLLECTION IN .NET MAUI

by

In this tutorial, you will learn how to use ObservableCollection in .NET MAUI. The ObservableCollection is a collection that provides notifications when items get added, removed, or when the whole list is refreshed. These notifications are useful when you want to update the UI automatically whenever the underlying data changes. This is achieved through the implementation of INotifyPropertyChanged and INotifyCollectionChanged interfaces.

Creating a .NET MAUI project

  1. Open Visual Studio 2022.
  2. Click on "Create a new project."
  3. Select the ".NET MAUI App" template and click "Next."
  4. Name your project, choose a location, and click "Create."

Using ObservableCollection

Let's start by creating a simple model class and an ObservableCollection of that model.

  1. Add a new class called Person to the project:
public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
  1. In the MainPage.xaml.cs file, create an ObservableCollection of Person:
using System.Collections.ObjectModel;
// ...
public partial class MainPage : ContentPage
{
    public ObservableCollection<Person> People { get; set; }
    // ...
}
  1. Initialize the People collection in the MainPage constructor:
public MainPage()
{
    InitializeComponent();
    People = new ObservableCollection<Person>
    {
        new Person { Name = "Alice", Age = 30 },
        new Person { Name = "Bob", Age = 25 },
        new Person { Name = "Charlie", Age = 22 }
    };
    BindingContext = this;
}
  1. Update the MainPage.xaml file to display the People collection using a ListView:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2022/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YourNamespace.MainPage">
    <StackLayout>
        <ListView ItemsSource="{Binding People}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Name}" Detail="{Binding Age}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

If you were to run your application at this point, you would see a list of people displayed on the screen.

See it in Action

To demonstrate the ObservableCollection in action, let's add a button that adds a new Person to the list when clicked. The ObservableCollection will automatically update the UI whenever the People collection changes.

  1. Update the MainPage.xaml file to include a button:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2022/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YourNamespace.MainPage">
    <StackLayout>
        <Button Text="Add Person" Clicked="OnAddPersonClicked" />
        <ListView ItemsSource="{Binding People}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding Name}" Detail="{Binding Age}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>
  1. Add the OnAddPersonClicked event handler in the MainPage.xaml.cs file:
private void OnAddPersonClicked(object sender, EventArgs e)
{
    People.Add(new Person { Name = "New Person", Age = 20 });
}

Now, when you run the application and click the "Add Person" button, a new Person will be added to the People collection, and the UI will automatically update to display the new item. This showcases the power of ObservableCollection in action.

Implementing INotifyPropertyChanged and INotifyCollectionChanged manually

If you were to implement the INotifyPropertyChanged and INotifyCollectionChanged interfaces manually, the code would look like this:

  1. Create a custom collection class that inherits from List<T> and implements INotifyCollectionChanged:
public class ObservableList<T> : List<T>, INotifyCollectionChanged
{
    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public new void Add(T item)
    {
        base.Add(item);
        CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
    }

    public new void Remove(T item)
    {
        if (base.Remove(item))
        {
            CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
        }
    }

    // Implement other methods like Clear, Insert, etc., following the same pattern.
}
  1. Update the Person class to implement INotifyPropertyChanged:
public class Person : INotifyPropertyChanged
{
    private string _name;
    private int _age;

    public string Name
    {
        get => _name;
        set
        {
            _name = value;
            OnPropertyChanged();
        }
    }

    public int Age
    {
        get => _age;
        set
        {
            _age = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. Finally, update the MainPage.xaml.cs file to use the ObservableList instead of ObservableCollection:
public ObservableList<Person> People { get; set; }

This manual implementation achieves the same behavior as using ObservableCollection, but it requires a lot more code. Using an ObservableCollection, on the other hand, provides a more convenient and less error-prone way to achieve the same functionality.

Nuances and Trade-offs of Using ObservableCollection

While ObservableCollection is a powerful tool for data binding in .NET MAUI applications, it is essential to understand its nuances and trade-offs.

  1. Bindable Properties: When using ObservableCollection, it is essential to make the properties bindable in your model. This can be achieved by implementing the INotifyPropertyChanged interface in your model (see above) or inheriting ObservableObject and using the SetProperty method to update the property values (see below). Failing to do this can lead to issues where the UI does not update correctly when the data changes. Please note that using ObservableObject requires the CommunityToolkit.Mvvm NuGet package to be installed in your project.
using CommunityToolkit.Mvvm.ComponentModel;

public class Person : ObservableObject
{
    private string _name;
    private int _age;

    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }

    public int Age
    {
        get { return _age; }
        set { SetProperty(ref _age, value); }
    }
}
  1. Performance: While ObservableCollection offers automatic UI updates, it may not be the most performant option for large data sets. The INotifyCollectionChanged and INotifyPropertyChanged events can cause a significant overhead when updating a large number of items. In such cases, using a List or other collection types and manually handling the UI updates might be more efficient.

  2. Not Suitable for All Scenarios: ObservableCollection is designed for scenarios where you need to track changes to a collection and automatically update the UI. If your application does not require this functionality, a simpler collection type like List might be more appropriate. Using ObservableCollection in situations where it is not needed can lead to unnecessary complexity and performance overhead.

In conclusion, while ObservableCollection is a powerful tool for data binding in .NET MAUI applications, it is essential to understand its nuances and trade-offs. Be mindful of its limitations in XAML usage, the need for bindable properties, potential performance issues, and suitability for your specific scenario. By being aware of these factors, you can make informed decisions about whether ObservableCollection is the right choice for your application and avoid common pitfalls.

The Bottom Line

In this tutorial, we have learned how to use ObservableCollection in .NET MAUI. We have seen how ObservableCollection automatically updates the UI whenever the underlying data changes. We have also seen how to add a Person object to the ObservableCollection using a button click event handler. Additionally, we have briefly explored how to implement INotifyPropertyChanged and INotifyCollectionChanged manually. It is important to note that ObservableCollection can be misused, and it is easy to make mistakes while using it. However, with proper care and attention, ObservableCollection is a powerful tool for data binding in .NET MAUI applications.


Don't stop learning!

There is so much to discover about C#. That's why I am making my favorite tips and tricks available for free. Enter your email address below to become a better .NET developer.


Did you know?

Our beautiful, multi-column C# reference guides contain more than 150 tips and examples to make it even easier to write better code.

Get your cheat sheets