2015-11-10 44 views
4

我有一個類幾十需要提高財產性質的改變事件,目前我的代碼看起來像短的代碼來觸發屬性更改事件

public class Ethernet : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string timeStamp; 

    public string TimeStamp 
    { 
     get { return timeStamp; } 
     set 
     { 
      timeStamp = value; 

      if(PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs("TimeStamp")); 
     } 
    } 
} 

有沒有在C#中的簡寫形式,這種的代碼,我爲每個屬性做了過多的複製/粘貼操作,我覺得必須有更好的方法。

+0

不是真的,但你可以使用工具,如Fody(免費)出PostSharp(付費),使其更容易。 –

+1

[實現INotifyPropertyChanged的可能的重複 - 有更好的方式嗎?](http://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist) – drf

回答

6

(意味着這是一個較短的評論,但顯然我不允許張貼之一,然而,MODS的,請隨時降級以下的評論。)

的引用代碼不是線程安全的,書面。請參閱Pattern for implementing INotifyPropertyChanged?爲什麼下面的代碼更好,以及在接受的答覆中,Eric Lippert博客的鏈接爲什麼故事沒有結束。

PropertyChangedEventHandler handler = PropertyChanged; 
    if (handler != null) handler(this, new PropertyChangedEventArgs("TimeStamp")); 

對於答案的實際問題,看到Implementing INotifyPropertyChanged - does a better way exist?包括本C#6.0的快捷方式。

PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TimeStamp")); 
+0

當'。?'返回null你會有這樣的'null;'的代碼行。這是不可能的,所以你會結束編譯時錯誤。 (但upvoted其他信息。) –

+1

@ M.kazemAkhgary - 不,新的c#6.0'。?'是一個空檢查代碼。它只在'。?'左邊的值不是'null'時調用'Invoke'。它編譯(在C#6.0)就好了。 – Enigmativity

+0

@ M.kazem我的理解是用。? null沒有調用,也沒有錯誤。除了在鏈接的stackoverflow答案中提到,這也是由Mark Michaelis&Eric Lippert撰寫的Essential C#6.0中的推薦方法(「高級主題:利用null-conditional操作符與代表」)。 – dxiv

1

請看看這個答案:https://stackoverflow.com/a/2339904/259769

我的代碼提供和擴展方法來取代大部分的設置代碼,並讓您縮短您的代碼如下:

public class Ethernet : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private string timeStamp; 

    public string TimeStamp 
    { 
     get { return timeStamp; } 
     set { this.NotifySetProperty(ref timeStamp, value,() => this.TimeStamp); } 
    } 
} 

這個代碼的另一個明顯的優點是它立即變成強屬於該屬性的名稱。

0

在MVVM模式,屬性改變/ ING經常被用來和一個典型的鹼性溶液如下:

public class ViewModelBase : INotifyPropertyChanged 
    { 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected void FirePropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     if (propertyName == null) 
      throw new ArgumentNullException("propertyName"); 
     try 
     { 
      this.OnPropertyChanged(propertyName); 
     } 
     catch (Exception exception) 
     { 
      Trace.TraceError("{0}.OnPropertyChanged threw {1}: {2}", this.GetType().FullName, exception.GetType().FullName, exception); 
     } 
    } 
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    } 

public class Ethernet : ViewModelBase 
    { 
    private DataTime timeStamp; 

    public DateTime TimeStamp 
    { 
     get 
     { 
      return timeStamp; 
     } 
     set 
     { 
      timeStamp = value; 
      FirePropertyChanged(); 
     } 
    } 
    } 
0

,我愛上了這個類:

[Serializable] 
public class PropertyChangedBase : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual bool SetProperty<T>(T value, ref T field, Expression<Func<object>> property) 
    { 
     return SetProperty(value, ref field, GetPropertyName(property)); 
    } 

    protected virtual bool SetProperty<T>(T value, ref T field, [CallerMemberName] string propertyName = null) 
    { 
     if (field == null || !field.Equals(value)) 
     { 
      field = value; 
      OnPropertyChanged(propertyName); 
      return true; 
     } 
     return false; 
    } 

    public void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    public void OnPropertyChanged(Expression<Func<object>> property) 
    { 
     OnPropertyChanged(GetPropertyName(property)); 
    } 

    protected string GetPropertyName(Expression<Func<object>> property) 
    { 
     var lambda = property as LambdaExpression; 
     MemberExpression memberExpression; 

     var unaryExpression = lambda.Body as UnaryExpression; 
     if (unaryExpression != null) 
     { 
      memberExpression = unaryExpression.Operand as MemberExpression; 
     } 
     else 
     { 
      memberExpression = (MemberExpression) lambda.Body; 
     } 

     var propertyInfo = memberExpression?.Member as PropertyInfo; 
     return propertyInfo?.Name ?? string.Empty; 
    } 
} 

巨大優勢這是它檢查值是否改變。這將最小化對視圖的更新調用。對於你的榜樣,它可以看起來像:

public class Ethernet : PropertyChangedBase 
{ 
    private string _timeStamp; 

    public string TimeStamp 
    { 
     get { return _timeStamp; } 
     set { SetProperty(value, ref _timeStamp); } 
    } 
} 

如果你想它真的很舒服,你可以寫一個代碼段。這將是段部分:

<Snippet> 
     <Declarations> 
     <Literal> 
      <ID>PropertyName</ID> 
      <Type>String</Type> 
      <ToolTip>The property name</ToolTip> 
      <Default>NewProperty</Default> 
     </Literal> 
     <Literal> 
      <ID>PropertyType</ID> 
      <Type> 
      </Type> 
      <ToolTip>Replace with the type of the property</ToolTip> 
      <Default>string</Default> 
     </Literal> 
     <Object> 
      <ID>PrivateVariable</ID> 
      <Type>Object</Type> 
      <ToolTip>The name of the private variable</ToolTip> 
      <Default>newPropertyValue</Default> 
     </Object> 
     </Declarations> 
     <Code Language="csharp" Kind="method decl"><![CDATA[  private $PropertyType$ _$PrivateVariable$; 
     public $PropertyType$ $PropertyName$ 
     { 
      get { return _$PrivateVariable$; } 
      set 
      { 
       SetProperty(value, ref _$PrivateVariable$); 
      } 
     }]]></Code> 
    </Snippet> 
相關問題