如果不使用类似postsharp的工具,我所使用的最简版本会使用以下内容:
public class Data : INotifyPropertyChanged
{
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;
}
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}
}
每个属性都只是类似于:
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}
这并不是很庞大的代码库;如果需要,它还可以用作基类。从SetField
返回的bool
告诉您是否是无操作,以防您想应用其他逻辑。
使用C# 5甚至更加简单:
protected bool SetField<T>(ref T field, T value,
[CallerMemberName] string propertyName = null)
{...}
可以这样调用:
set { SetField(ref name, value); }
使用编译器可以自动添加"Name"
,这使得实现更加容易。
C# 6.0使实现变得更加简单:
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
现在,使用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);
}
使用C# 8和可空引用类型,代码将如下所示:
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);
}