Is there some way to avoid this. I have a lot of classes that are bound to DataGridViews and they are just simple collection of properties with default getter and setter. So
Create a container base class, eg:
abstract class Container : INotifyPropertyChanged
{
Dictionary<string, object> values;
protected object this[string name]
{
get {return values[name]; }
set
{
values[name] = value;
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
class Foo : Container
{
public int Bar
{
{get {return (int) this["Bar"]; }}
{set { this["Bar"] = value; } }
}
}
Note: very simplified code
Using code gen (say, T4) is another way. Check the discussion at: Automatic INotifyPropertyChanged Implementation through T4 code generation?.
I use this method, and it works well.
Without AOP, I don't think there is an easy way to retrofit this to your existing classes. However you do it, you're at the very least going to have to change all your properties.
I use a base class inheriting INotifyPropertyChanged with an OnPropertyChanged(string propertyName) method to fire the event. I then use a Visual Studio Code snippet to create properties that automatically call OnPropertyChanged in the property setter.
It depends; you could use PostSharp to write such an attribute that is re-written by the weaver; however, I would be tempted to just do it manually - perhaps using a common method for handling the data updates, i.e.
private string name;
public string Name {
get { return name; }
set { Notify.SetField(ref name, value, PropertyChanged, this, "Name"); }
}
with:
public static class Notify {
public static bool SetField<T>(ref T field, T value,
PropertyChangedEventHandler handler, object sender, string propertyName)
{
if(!EqualityComparer<T>.Default.Equals(field,value)) {
field = value;
if(handler!=null) {
handler(sender, new PropertyChangedEventArgs(propertyName));
}
return true;
}
return false;
}
}
I have just found ActiveSharp - Automatic INotifyPropertyChanged, I have yet to use it, but it looks good.
To quote from it's web site...
Send property change notifications without specifying property name as a string.
Instead, write properties like this:
public int Foo
{
get { return _foo; }
set { SetValue(ref _foo, value); } // <-- no property name here
}
Note that there is no need to include the name of the property as a string. ActiveSharp reliably and correctly figures that out for itself. It works based on the fact that your property implementation passes the backing field (_foo) by ref. (ActiveSharp uses that "by ref" call to identify which backing field was passed, and from the field it identifies the property).
If you're amenable to AOP, you could try using PostSharp. Search for PostSharp INotifyPropertyChanged and you'll find lots of articles explaining it, such as this and this.