WPF: Editable DataGrid and ObservableDictionary

An observable dictionary is not included in WPF by default, but it would be useful to have one to be able to bind to an editable DataGrid. In this article we will “cheat” a bit, and quickly make use of the ObservableCollection to create a new type similar to an observable dictionary.

You cannot use a dictionary directly in an editable DataGrid, because the KeyValuePairs are read only and don’t implement the INotifyPropertyChanged interface.

But by creating a new pair class and subclassing ObservableCollection we can imitate an observable dictionary.

An observable pair class

Let’s start with the Pair class:

public class Pair<TKey, TValue> : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected TKey _key;
    protected TValue _value;
 
    public TKey Key
    {
        get { return _key; }
        set
        {
            if (
                (_key == null && value != null)
                || (_key != null && value == null)
                || !_key.Equals(value))
            {
                _key = value;
                NotifyPropertyChanged("Key");
            }
        }
    }
 
    public TValue Value
    {
        get { return _value; }
        set
        {
            if (
                (_value == null && value != null)
                || (_value != null && value == null)
                || (_value != null && !_value.Equals(value)))
            {
                _value = value;
                NotifyPropertyChanged("Value");
            }
        }
    }
}

And now let’s include constructors and methods:

public class Pair<TKey, TValue> : INotifyPropertyChanged
{
    public Pair()
    {
    }
 
    public Pair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }
 
    public Pair(KeyValuePair<TKey, TValue> kv)
    {
        Key = kv.Key;
        Value = kv.Value;
    }
 
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Observable pair collection

Creating a new type of observable collection similar to a dictionary:

public class ObservablePairCollection<TKey, TValue> : ObservableCollection<Pair<TKey, TValue>>
{
    public ObservablePairCollection()
        : base()
    {
    }
 
    public ObservablePairCollection(IEnumerable<Pair<TKey, TValue>> enumerable)
        : base(enumerable)
    {
    }
 
    public ObservablePairCollection(List<Pair<TKey, TValue>> list)
        : base(list)
    {
    }
 
    public ObservablePairCollection(IDictionary<TKey, TValue> dictionary)
    {
        foreach (var kv in dictionary)
        {
            Add(new Pair<TKey, TValue>(kv));
        }
    }
 
    public void Add(TKey key, TValue value)
    {
        Add(new Pair<TKey, TValue>(key, value));
    }
}

But you don’t have to stop there. It wouldn’t be very difficult to implement the IDictionary interface and have an actual dictionary, but in most cases this will actually suffice.

Using in an editable DataGrid

Let’s make use of this in an editable DataGrid.

Declare the property in your view model:

readonly ObservablePairCollection<string, string> _countries;

public ObservablePairCollection<string, string> Countries { get { return _countries; } }

And create some dummy data:

public MainWindowViewModel()
{
    _countries = new ObservablePairCollection<string, string>();
    _countries.Add("Ascension Island", "AC");
    _countries.Add("Andorra", "AD");
    _countries.Add("United Arab Emirates", "AE");
    _countries.Add("Afghanistan", "AF");
    _countries.Add("Antigua and Barbuda", "AG");
    // etc.
}

Just include the control in XAML:

<DataGrid ItemsSource="{Binding Countries}" />

And the result is the following:

Editable DataGrid with observable pair collection
Editable DataGrid with observable pair collection
Nuno Freitas
Posted by Nuno Freitas on March 21, 2014

Related articles