Fody/PropertyChanged(二)

时间:2022-06-28 06:24:12

前一篇 简单的介绍了Fody/PropertyChanged的使用方法, 这一篇,我们详细介绍它的一些比较重要的特性和规则

1. Attributes

通过在类或属性上标记这些特性,可以在编译代码时,注入特定的功能

ImplementPropertyChangedAttribute

为类标记此特性,可以实现INotifyPropertyChanged接口

[ImplementPropertyChanged] public class Person { public string Name { get; set; } } AlsoNotifyForAttribute

在实现通知时,也同时通知其它属性

public class Person : INotifyPropertyChanged { [AlsoNotifyFor("FullName")] public string GivenName { get; set; } [AlsoNotifyFor("FullName")] public string FamilyName { get; set; } public event PropertyChangedEventHandler PropertyChanged; public string FullName { get; set; } }

在GivenName或FamilyName变化时,会同时也通知FullName的变化

DoNotNotifyAttribute

顾名思义,就是在编译时,不在此属性中注入变化通知的代码

public class Person : INotifyPropertyChanged { public string GivenName { get; set; } [DoNotNotify] public string FamilyName { get; set; } public event PropertyChangedEventHandler PropertyChanged; } DependsOnAttribute

设置一个属性,在它依赖的属性变化时,通知此属性发生变化

public class Person : INotifyPropertyChanged { public string GivenName { get; set; } public string FamilyName { get; set; } public event PropertyChangedEventHandler PropertyChanged; [DependsOn("GivenName","FamilyName")] public string FullName { get; set; } } DoNotSetChangedAttribute

通过约定,在实现的类里,如果有一个属性是IsChanged

public bool IsChanged { get; set; }

在其它类发生变化时,此类的值会自动被设置为True,

如果希望在某个属性变化时,,不响应此规则,可以将属性标记为DoNotSetChangedAttribute

public class Person: INotifyPropertyChanged { [DoNotSetChanged] public string FullName { get; set; } public bool IsChanged { get; set; } public event PropertyChangedEventHandler PropertyChanged; }

在FullName变化里,不会将IsChanged设置为True

DoNotCheckEqualityAttribute

默认情况下,所有注入的变化响应,都会检查是否相等,如果相等,则不会进行通知;但在某些时候,我们也许需要无论是否相等都进行通知,这个时候,可以在属性上标记DoNotCheckEqualityAttribute以跳过是否相等的检查

public class Person: INotifyPropertyChanged { [DoNotCheckEquality] public string FullName { get; set; } public bool IsChanged { get; set; } public event PropertyChangedEventHandler PropertyChanged; }

这样,在给FullName赋值时,无论是否和之前的值相等,都会进行通知。

2. BeforeAfter

有时候,我们需要在值发生变化时,访问变化之前和之后的值,比如做验证时,我们可以通过加入下面的方法实现:

public void OnPropertyChanged(string propertyName, object before, object after)

比如,我们写的代码:

public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public string Name { get; set; } public void OnPropertyChanged(string propertyName, object before, object after) { //Perform property validation var propertyChanged = PropertyChanged; if (propertyChanged != null) { propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }

在编译时,对应的代码为:

public class Person : INotifyPropertyChanged { private string name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return name; } set { object before = Name; name = value; OnPropertyChanged("Name", before, Name); } } public void OnPropertyChanged(string propertyName, object before, object after) { //Perform property validation var propertyChanged = PropertyChanged; if (propertyChanged != null) { propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } 3. EqualityChecking

在设置属性的值之前,会进行是否相等的检查:

public string Property1 { get { return property1; } set { if (!String.Equals(property1, value)) { property1 = value; OnPropertyChanged("Property1"); } } }

用于检查是否相等的方法依赖于属性的数据类型,按照下面的顺序或规则进行比较:

如果类型是Nullable,则使用 Nullable.Equals(T?,T?)方法比较

如果类型包含有静态的方法Equals,则使用静态的方法对比两个参数

如果类型有==方法,则使用==比较参数

使用Object.Equals(object,object)比较

4.实现IsChanged标志

在上面我们已经简单的介绍了IsChanged属性,具体的实现代码如下:

书写的代码

public class Person : INotifyPropertyChanged { public string Name { get; set; } public event PropertyChangedEventHandler PropertyChanged; public bool IsChanged { get; set; } }

编译对应的代码 (省略比较的代码

public class Person : INotifyPropertyChanged { string name; bool isChanged; public event PropertyChangedEventHandler PropertyChanged; public virtual void OnPropertyChanged(string propertyName) { var propertyChanged = PropertyChanged; if (propertyChanged != null) { propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public string Name { get { return name; } set { name = value; IsChanged = true; OnPropertyChanged("Name"); } } public bool IsChanged { get { return isChanged; } set { isChanged = value; OnPropertyChanged("IsChanged"); } } }

这样,在Name设置新值后,IsChanged属性会被设置为True

当然,在代码逻辑中,在适当的时候需要手动将IsChanged设置为false

还有一些配置和规则,可以参见https://github.com/Fody/PropertyChanged/wiki