Skip to main content

Observable Collections

Observable collections provide automatic change notification for collections in Avalonia UI, enabling UI elements to automatically update when items are added, removed, or changed.

AvaloniaList<T>

Avalonia’s built-in observable list implementation.

Namespace

Avalonia.Collections

Inheritance

Object → AvaloniaList\<T\>
Implements: IList\<T\>, INotifyCollectionChanged, INotifyPropertyChanged

Constructor

public AvaloniaList\<T\>()
public AvaloniaList\<T\>(IEnumerable\<T\> items)
public AvaloniaList\<T\>(int capacity)

Properties

Count
int
Gets the number of items in the collection.
Item[int index]
T
Gets or sets the item at the specified index.

Methods

Add
void
Adds an item to the collection.Parameters:
  • item (T): The item to add
AddRange
void
Adds multiple items to the collection in a single operation.Parameters:
  • items (IEnumerable<T>): The items to add
Remove
bool
Removes an item from the collection.Parameters:
  • item (T): The item to remove
Returns: true if the item was removed
RemoveAt
void
Removes the item at the specified index.Parameters:
  • index (int): The index of the item to remove
Clear
void
Removes all items from the collection.
Insert
void
Inserts an item at the specified index.Parameters:
  • index (int): The index to insert at
  • item (T): The item to insert
Move
void
Moves an item from one index to another.Parameters:
  • oldIndex (int): The current index
  • newIndex (int): The new index

Events

CollectionChanged
NotifyCollectionChangedEventHandler
Occurs when the collection changes (items added, removed, moved, or reset).
PropertyChanged
PropertyChangedEventHandler
Occurs when a property value changes (typically Count or Item[]).

Usage Examples

Basic ViewModel with ObservableCollection

using Avalonia.Collections;
using CommunityToolkit.Mvvm.ComponentModel;

public partial class MainViewModel : ObservableObject
{
    public AvaloniaList<Person> People { get; } = new();
    
    public MainViewModel()
    {
        // Initialize collection
        People.Add(new Person { Name = "Alice", Age = 30 });
        People.Add(new Person { Name = "Bob", Age = 25 });
    }
    
    public void AddPerson(string name, int age)
    {
        People.Add(new Person { Name = name, Age = age });
    }
    
    public void RemovePerson(Person person)
    {
        People.Remove(person);
    }
}

public partial class Person : ObservableObject
{
    [ObservableProperty]
    private string name = "";
    
    [ObservableProperty]
    private int age;
}

Binding to ListBox

<ListBox ItemsSource="{Binding People}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Name}" FontWeight="Bold" />
                <TextBlock Text="{Binding Age}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Adding Multiple Items

// Add items individually (triggers change notification for each)
People.Add(person1);
People.Add(person2);
People.Add(person3);

// Better: Add multiple items at once (single change notification)
People.AddRange(new[] { person1, person2, person3 });

Collection Change Notification

People.CollectionChanged += (sender, e) =>
{
    switch (e.Action)
    {        case NotifyCollectionChangedAction.Add:
            Console.WriteLine($"Added {e.NewItems?.Count} item(s)");
            break;
        
        case NotifyCollectionChangedAction.Remove:
            Console.WriteLine($"Removed {e.OldItems?.Count} item(s)");
            break;
        
        case NotifyCollectionChangedAction.Move:
            Console.WriteLine("Item moved");
            break;
        
        case NotifyCollectionChangedAction.Reset:
            Console.WriteLine("Collection reset");
            break;
    }
};

System.Collections.ObjectModel.ObservableCollection<T>

You can also use the standard .NET ObservableCollection\<T\> which is fully supported:
using System.Collections.ObjectModel;

public class MainViewModel
{
    public ObservableCollection<Person> People { get; } = new();
}
Both AvaloniaList\<T\> and ObservableCollection\<T\> work with Avalonia’s data binding system. AvaloniaList\<T\> provides additional methods like AddRange for batch operations.

Filtered and Sorted Collections

Using DataGridCollectionView (for filtering/sorting)

using Avalonia.Controls;

public class MainViewModel
{
    private readonly AvaloniaList<Person> _allPeople = new();
    
    public DataGridCollectionView PeopleView { get; }
    
    public MainViewModel()
    {
        PeopleView = new DataGridCollectionView(_allPeople);
        
        // Add filtering
        PeopleView.Filter = obj => obj is Person p && p.Age >= 18;
        
        // Add sorting
        PeopleView.SortDescriptions.Add(
            new DataGridSortDescription(nameof(Person.Name), ListSortDirection.Ascending)
        );
    }
}

Performance Tips

When adding multiple items, use AddRange instead of calling Add multiple times to reduce change notifications.
// Bad: Multiple change notifications
foreach (var item in newItems)
    People.Add(item);

// Good: Single change notification
People.AddRange(newItems);
For large collections in ListBox or similar controls, enable virtualization:
<ListBox ItemsSource="{Binding LargeCollection}"
         VirtualizationMode="Simple" />
For the UI to update when item properties change, your item class must implement INotifyPropertyChanged or use ObservableObject from CommunityToolkit.Mvvm.

See Also

Build docs developers (and LLMs) love