ObservableCollection
.NET
data binding
C#
WPF

What is the use of ObservableCollection in .net?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

ObservableCollection<T> is a .NET collection type built for data-binding scenarios where the UI should react when items are added, removed, moved, or replaced. It is especially common in WPF, WinUI, MAUI, and MVVM-style applications because it raises change notifications that bound controls can listen to automatically.

Why ObservableCollection<T> Exists

A plain List<T> works well as a data structure, but it does not notify the UI when the collection changes. If you bind a List<T> to a control and then add or remove items later, the view usually will not refresh automatically.

ObservableCollection<T> solves that by implementing INotifyCollectionChanged.

csharp
1using System;
2using System.Collections.ObjectModel;
3using System.Collections.Specialized;
4
5class Program
6{
7    static void Main()
8    {
9        var names = new ObservableCollection<string>();
10        names.CollectionChanged += OnCollectionChanged;
11
12        names.Add("Alice");
13        names.Add("Bob");
14        names.Remove("Alice");
15    }
16
17    static void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
18    {
19        Console.WriteLine($"Action: {e.Action}");
20    }
21}

That notification mechanism is the main reason the type exists.

Typical UI Binding Usage

In MVVM, a view model often exposes an ObservableCollection<T> for a list control.

csharp
1using System.Collections.ObjectModel;
2using System.ComponentModel;
3
4public class UserViewModel : INotifyPropertyChanged
5{
6    public ObservableCollection<string> Users { get; } = new();
7
8    private string _status = "Ready";
9    public string Status
10    {
11        get => _status;
12        set
13        {
14            if (_status != value)
15            {
16                _status = value;
17                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Status)));
18            }
19        }
20    }
21
22    public event PropertyChangedEventHandler? PropertyChanged;
23}

If a ListBox, ListView, or DataGrid is bound to Users, adding or removing items from the collection updates the control without requiring a manual refresh.

Collection Changes Versus Item Property Changes

This distinction is crucial:

  • 'ObservableCollection<T> notifies when collection membership changes'
  • 'INotifyPropertyChanged notifies when a property on an individual item changes'

If the collection contains objects and one object's Name property changes, the UI updates correctly only if that object implements INotifyPropertyChanged.

csharp
1public class User : INotifyPropertyChanged
2{
3    private string _name = "";
4
5    public string Name
6    {
7        get => _name;
8        set
9        {
10            if (_name != value)
11            {
12                _name = value;
13                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
14            }
15        }
16    }
17
18    public event PropertyChangedEventHandler? PropertyChanged;
19}

Many developers expect ObservableCollection<T> alone to cover both cases, but it only covers collection-level changes.

Threading and UI Dispatch

UI-bound collections usually must be modified on the UI thread. If background work loads data and then mutates the bound collection directly, many UI frameworks throw cross-thread exceptions.

csharp
1using System.Threading.Tasks;
2using System.Windows;
3
4public async Task LoadUsersAsync(ObservableCollection<string> users)
5{
6    var fetched = await Task.Run(() => new[] { "Ada", "Grace", "Linus" });
7
8    Application.Current.Dispatcher.Invoke(() =>
9    {
10        foreach (var user in fetched)
11        {
12            users.Add(user);
13        }
14    });
15}

The exact dispatcher API depends on the UI framework, but the principle stays the same: update the bound collection on the thread the UI expects.

Performance and Bulk Updates

ObservableCollection<T> raises notifications per change. That is excellent for interactive edits and sometimes expensive for bulk loads.

If you add thousands of items one by one, the UI may refresh repeatedly and become sluggish. Common responses include:

  • loading in chunks
  • swapping in a fully built collection
  • using a custom collection with batch notification behavior

The right choice depends on the framework and the size of the data, but it is important to know that observability has a runtime cost.

When to Use Something Else

Use List<T> when you do not need change notifications. Use ReadOnlyObservableCollection<T> when consumers should observe updates but not mutate directly. If you need advanced sorting, filtering, paging, or virtualization behavior, ObservableCollection<T> may be only part of the solution rather than the entire data layer.

Common Pitfalls

The most common mistake is expecting item property changes to update the UI when the item type does not implement INotifyPropertyChanged. Another is modifying a UI-bound collection from a background thread. Developers also use ObservableCollection<T> for huge datasets without virtualization or batching and then blame the control when the real issue is the volume of per-item notifications.

Summary

  • 'ObservableCollection<T> is designed for data binding with automatic collection change notifications.'
  • It is useful when UI lists should update as items are added or removed.
  • It does not replace INotifyPropertyChanged on individual items.
  • UI-bound collection changes usually need to happen on the UI thread.
  • For large updates, plan for batching, chunking, or a more specialized collection strategy.

Course illustration
Course illustration

All Rights Reserved.