WPF開發進階 - Fody/PropertyChanged(二)


前一篇 簡單的介紹了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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM