I Changed INotifyPropertyChanged
Tags: wpf, csharp, ui, dotnet
Published: 2018-09-09 06:25:49

---
title: I Changed INotifyPropertyChanged
published: true
description: A simpler approach to INotifyPropertyChanged
tags: wpf, csharp, ui, dotnet 
---

##The original approach to INotifyPropertyChanged.
Hi all, it has always bothered me that one has to type so much code in order to implement property binding notification for every property.

```cs
public class MyViewModel : INotifyPropertyChanged
{
    private int _myProperty;

    public int MyProperty
    {
        get => _myProperty;
        set
        {
            _myProperty = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
```

##A simpler approach to INotifyPropertyChanged

However, I got an idea from [this creative Stack Overflow answer](https://stackoverflow.com/a/3130521):

```cs
public abstract class Container : INotifyPropertyChanged
{
    Dictionary<string, object> values;

    public event PropertyChangedEventHandler PropertyChanged;

    protected object this[string name]
    {
        get => values[name];
        set 
        { 
            values[name] = value;
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
}
```
```cs
public class Foo : Container
{
    public int Bar 
    {
        get => (int) this["Bar"];
        set => this["Bar"] = value;
    }
}
```

I decided to use a similar approach because:
 - The solution above did not handle a case where there is no such element in the `values` dictionary (which results in a [`KeyNotFoundException`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.keynotfoundexception?view=netframework-4.7.2))
 - I wanted to avoid passing the name of the property (the solution is the [`CallerMemberName`](https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.callermembernameattribute?view=netframework-4.7.2) attribute, that is being used in the original approach) 
 - I preferred to use generic methods rather than indexers (`["name"]`).

```cs
public class PropertyChangedHelper : INotifyPropertyChanged
{
    private readonly Dictionary<string, object> _values = new Dictionary<string, object>();

    public event PropertyChangedEventHandler PropertyChanged;

    public T GetProperty<T>([CallerMemberName] string propertyName = "")
    {
        EnsureElement<T>(propertyName);
        return (T) _values[propertyName];
    }

    public void SetProperty<T>(object value, [CallerMemberName] string propertyName = "")
    {
        EnsureElement<T>(propertyName);
        if (_values[propertyName] == value)
        {
            return;
        }
        _values[propertyName] = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private void EnsureElement<T>(string propertyName)
    {
        if (!_values.ContainsKey(propertyName))
        {
            _values.Add(propertyName, default(T));
        }
    }
}
```
```cs
public class MyViewModel : PropertyChangedHelper
{
    public bool MyProperty
    {
        get => GetProperty<int>();
        set => SetProperty<int>(value);
    }
}
```

## Performance

Thanks a lot for benchmarking this solution for me! {% user jeuxjeux20 %} 

Some of you may be skeptic about the approach above, so a friend of mine - `jeuxjeux20` has benchmarked (Using [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet)) the original, longer approach to property binding notification, and the new, hassle-free approach:



| Method                                   	| Mean (Time) 	| Error (Margin) 	| Standard Deviation 	|
|------------------------------------------	|-------------	|----------------	|--------------------	|
| **GetPropertyValue (Original Approach)** 	| 46.3   ns   	| 0.0818 ns      	| 0.0765 ns          	|
| **SetPropertyValue (Original Approach)** 	| 238.16 ns   	| 1.8122 ns      	| 1.6951 ns          	|
| **GetPropertyValue (New Approach)**      	| 213.09 ns   	| 2.8977 ns      	| 2.7105 ns          	|
| **SetPropertyValue (New Approach)**      	| 539.47 ns   	| 3.7321 ns      	| 3.4910 ns          	|
 - *ns = nanosecond (1/1,000,000,000 of a second)*

The code that `jeuxjeux20` wrote in order to test the approach:
{% gist https://gist.github.com/TheMulti0/7c5311b0a14702f5fb9126a2f08462ff %}

# Final Words
Thanks for reading this post!
I hope it has helped you creating a more elegant solution for property binding notification for your properties!

 - Multi!