[英]Shorter code to trigger property changed events
我有一個包含數十個屬性的類,需要引發屬性更改事件,目前我的代碼看起來像
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# 中是否有更短的方法來編寫這種代碼,我對每個屬性都做了過多的復制/粘貼操作,我覺得必須有更好的方法。
引用的代碼不是寫的線程安全的。 請參閱實現 INotifyPropertyChanged 的模式? 為什么下面的代碼更好,以及在接受的回復中指向 Eric Lippert 博客的鏈接為什么故事沒有就此結束。
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs("TimeStamp"));
有關實際問題的答案,請參閱實現 INotifyPropertyChanged - 是否存在更好的方法? 包括這個 C# 6.0 快捷方式。
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TimeStamp"));
看看這個答案: 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); }
}
}
這段代碼的另一個明顯優點是它立即變成了針對屬性名稱的強類型。
在 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();
}
}
}
我愛上了這門課:
[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>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.