WPF Development, INotifyCollectionChanged

WPF (Windows Presentation Foundation) is a GUI framework provided by Microsoft that supports powerful data binding and flexible UI design. Handling collections and data in WPF is very important, and in this process, the INotifyCollectionChanged interface plays a key role. In this article, we will deeply explain the concept of the INotifyCollectionChanged interface, how to use it, and how to utilize it through practical examples.

What is INotifyCollectionChanged?

INotifyCollectionChanged is an interface that provides events to notify changes that occur when items are added, removed, or modified in a collection. This interface is primarily used in MVVM (Model-View-ViewModel) architectures like WPF where data binding occurs.

The View receives data bound from the Model and listens for events through INotifyCollectionChanged to reflect changes in the model. When changes occur in the collection, the CollectionChanged event is triggered, and the UI is automatically updated.

Methods of INotifyCollectionChanged Interface

This interface defines the following event.

  • CollectionChanged: An event that notifies changes in the collection. This event has the following parameters:
    • sender: The object that raised the event.
    • args: An object of type NotifyCollectionChangedEventArgs, which contains information about the changes.

Additionally, NotifyCollectionChangedEventArgs can use the NotifyCollectionChangedAction enumeration to indicate the type of change. The types of changes include:

  • Add: An item has been added.
  • Remove: An item has been removed.
  • Replace: An item has been replaced.
  • Move: An item’s position has changed.
  • Reset: The collection has been reset.

Example: Usage of INotifyCollectionChanged

Now, let’s look at a simple example of using the INotifyCollectionChanged interface. In this example, we will create a custom collection class and show how the UI automatically updates according to changes in the collection.

Step 1: Create a Custom Collection Class

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;

public class ObservableCollectionEx<T> : ICollection<T>, INotifyCollectionChanged 
{
    private readonly List<T> _items;

    public ObservableCollectionEx() 
    {
        _items = new List<T>();
    }

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public void Add(T item) 
    {
        _items.Add(item);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
    }

    public void Remove(T item) 
    {
        if (_items.Remove(item)) 
        {
            OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
        }
    }

    protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
    {
        CollectionChanged?.Invoke(this, e);
    }

    public int Count => _items.Count;


    public bool IsReadOnly => false;

    public void Clear() 
    {
        _items.Clear();
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    public bool Contains(T item) 
    {
        return _items.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex) 
    {
        _items.CopyTo(array, arrayIndex);
    }

    public IEnumerator<T> GetEnumerator() 
    {
        return _items.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() 
    {
        return GetEnumerator();
    }

    public bool Remove(T item) 
    {
        return _items.Remove(item);
    }
}

Step 2: Create a WPF View

<Window x:Class="WpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox Name="ItemsListBox" />
        <Button Content="Add Item" Width="100" Height="30" Click="AddItem_Click" />
    </Grid>
</Window>

Step 3: Write the Code Behind

using System.Windows;

public partial class MainWindow : Window 
{
    private ObservableCollectionEx<string> _items;

    public MainWindow() 
    {
        InitializeComponent();
        _items = new ObservableCollectionEx<string>();
        _items.CollectionChanged += Items_CollectionChanged;
        ItemsListBox.ItemsSource = _items;
    }

    private void AddItem_Click(object sender, RoutedEventArgs e) 
    {
        _items.Add("New Item " + (_items.Count + 1));
    }

    private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    {
        // Additional processing can be done here when the collection changes.
    }
}

Check Final Result

Now, when the program runs, a new item will be added to the ListBox each time the “Add Item” button is clicked. Thanks to INotifyCollectionChanged, the ListBox automatically responds to changes in the collection and updates the UI.

Conclusion

The INotifyCollectionChanged interface makes UI updates through data binding in WPF very straightforward. By effectively utilizing this interface, you can structure WPF applications that use the MVVM architecture more efficiently. It is very useful in creating custom collections easily and simplifying data synchronization with the UI.

Through this article, I hope you have gained a sufficient understanding of INotifyCollectionChanged and its usage. Try to implement this concept to achieve powerful data management in your WPF applications, even in more complex scenarios.