How to Implement Inotifypropertychanged in C# 6.0

How to implement INotifyPropertyChanged in C# 6.0?

After incorporating the various changes, the code will look like this. I've highlighted with comments the parts that changed and how each one helps

public class Data : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
//C# 6 null-safe operator. No need to check for event listeners
//If there are no listeners, this will be a noop
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

// C# 5 - CallMemberName means we don't need to pass the property's name
protected bool SetField<T>(ref T field, T value,
[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}

private string name;
public string Name
{
get { return name; }
//C# 5 no need to pass the property name anymore
set { SetField(ref name, value); }
}
}

Implementing INotifyPropertyChanged - does a better way exist?

Without using something like postsharp, the minimal version I use uses something like:

public class Data : INotifyPropertyChanged
{
// boiler-plate
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, string propertyName)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}

// props
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}
}

Each property is then just something like:

private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}

which isn't huge; it can also be used as a base-class if you want. The bool return from SetField tells you if it was a no-op, in case you want to apply other logic.


or even easier with C# 5:

protected bool SetField<T>(ref T field, T value,
[CallerMemberName] string propertyName = null)
{...}

which can be called like this:

set { SetField(ref name, value); }

with which the compiler will add the "Name" automatically.


C# 6.0 makes the implementation easier:

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

...and now with C#7:

protected void OnPropertyChanged(string propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value,[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}

private string name;
public string Name
{
get => name;
set => SetField(ref name, value);
}

And, with C# 8 and Nullable reference types, it would look like this:

public event PropertyChangedEventHandler? PropertyChanged;

protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}

private string name;
public string Name
{
get => name;
set => SetField(ref name, value);
}

How to implement INotifyPropertyChanged with nameof rather than magic strings?

It would look like this:

public string Foo
{
get
{
return this.foo;
}
set
{
if (value != this.foo)
{
this.foo = value;
OnPropertyChanged(nameof(Foo));
}
}
}

The nameof(Foo) will be substituted with the "Foo" string at compile time, so it should be very performant. This is not reflection.

using of INotifyPropertyChanged

You need INotifyPropertyChanged if you want a wpf form to be automatically updated when a property changes through code. Also some controllers might want to know if edits have been made in order to enable/disable a save-button, for instance. You also might be displaying the same property on different views; in this case INotifyPropertyChanged helps to immediately update the other view when you edit a property.

If you think that your form behaves well without INotifyPropertyChanged, then you can drop it.

Note that binding works even without INotifyPropertyChanged. See: Why does the binding update without implementing INotifyPropertyChanged?


I would implement the properties like this. In some rare cases it can help to avoid endless circular updates. And it is more efficient by the way.

 private string _firstName;
public string StudentFirstName
{
get { return _firstName; }
set
{
if (value != _firstName) {
_firstName = value;
OnPropertyChanged("StudentFirstName");
}
}
}

Starting with C#6.0 (VS 2015), you can implement OnPropertyChanged like this:

private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

INotifyPropertyChanged and Auto-Properties

There's no built-in mechanism to do this. Something like PostSharp would likely be able to add something like this for you (or Mark Gravell's HyperDescriptor, if you're just interested in making this databinding-aware).

Implementing INotifyPropertyChanged - does a better way exist without using AOP?

Without code generation i know only one solution - use Castle Dynamic Proxy and interceptor as described here: http://jonas.follesoe.no/oldblog/2009-12-23-automatic-inotifypropertychanged-using-dynamic-proxy/

INotifyChangedProperty dynamic implementation

You can use the [CallerMemberName] if you are using .NET Framework 4.5

so your code will be :

using System.Runtime.CompilerServices;

class BetterClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Check the attribute in the following line :
private void FirePropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}

private int sampleIntField;

public int SampleIntProperty
{
get { return sampleIntField; }
set
{
if (value != sampleIntField)
{
sampleIntField = value;
// no "magic string" in the following line :
FirePropertyChanged();
}
}
}
}

as described in the question INotifyPropertyChanged : is [CallerMemberName] slow compared to alternatives?



Related Topics



Leave a reply



Submit