Refactoring PropertyChangedEventHandler
In my UI code I have a lot classes with the same basic skeleton:
- derives from INotifyPropertyChanged
contains the following code:
void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } public event PropertyChangedEventHandler PropertyChanged;
It seems like a perfect chance to factor into a class and 开发者_开发问答to derive from that instead of INotifyPropertyChanged, but sadly C# doesn't support multiple inheritance so it's not really going to work. Any ideas on how to refactor this kind of code?
Can't you just put this code into your superclass's superclass?
- Object
- Your concrete NotifyPropertyChanged class <-- Insert here
- Whatever your viewmodel inherited from (and stopped you using multiple inheritance
- Your concrete viewmodel
- Another concrete viewmodel
- Whatever your viewmodel inherited from (and stopped you using multiple inheritance
- Your concrete NotifyPropertyChanged class <-- Insert here
Most MVVM Frameworks provide such a class for you.
Because of the access rules around events, you can't factor this out into an extension method without reflection, unfortunately.
Maybe you can use something like this:
class A1 : INotifyPropertyChanged
{
private string _myProperty;
private static Expression<Func<A1, string>> myProperty = _ => _.MyProperty;
public string MyProperty
{
get { return _myProperty; }
set
{
_myProperty = value;
InvokePropertyChanged(myProperty);
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void InvokePropertyChanged<T>(Expression<Func<A1, T>> property)
{
PropertyChangedEventHandler Handler = PropertyChanged;
if (Handler != null)
{
MemberExpression expression = (MemberExpression)property.Body;
Handler(this, new PropertyChangedEventArgs(expression.Member.Name));
}
}
}
This significally reduce future code changes;)
Or you can use Postsharp plug-in that automatically implements INotifyPropertyChanged.
A common practice is to have a base class implementing INotifyPropertyChanged, like this:
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Then your classes will derive from this one, and you can call OnPropertyChanged when you wish to notify changes on the value of a property :
public class PersonViewModel : ViewModelBase
{
public PersonViewModel(Person person)
{
this.person = person;
}
public string Name
{
get
{
return this.person.Name;
}
set
{
this.person.Name = value;
OnPropertyChanged("Name");
}
}
}
It is 4 lines of code that will never change. Create a snippet!
This is probably a small help but you could use the params keyword so that you could change more than one property at a time.
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertiesChanged(params string[] Properties)
{
if (PropertyChanged != null)
foreach (string property in Properties)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
This decreases the amount of lines you use when notifying property changes in the future. So you use:
NotifyPropertiesChanged("foo", "bar");
Instead of:
NotifyPropertyChanged("foo"); NotifyPropertyChanged("bar");
Otherwise, I agree with Anders' suggestion of moving it up the inheritance tree would probably be best.
精彩评论