微软应该为INotifyPropertyChanged实现一些时髦的东西,就像在自动属性中,只需要指定{get;设置;通知;} 我认为这样做很有意义。或者做这个手术有什么并发症吗?
我们能在属性中实现类似notify的东西吗。在你的类中实现INotifyPropertyChanged是否有一个优雅的解决方案,或者唯一的方法是在每个属性中引发PropertyChanged事件。
如果不是,我们可以写一些东西来自动生成一段代码来引发PropertyChanged事件?
微软应该为INotifyPropertyChanged实现一些时髦的东西,就像在自动属性中,只需要指定{get;设置;通知;} 我认为这样做很有意义。或者做这个手术有什么并发症吗?
我们能在属性中实现类似notify的东西吗。在你的类中实现INotifyPropertyChanged是否有一个优雅的解决方案,或者唯一的方法是在每个属性中引发PropertyChanged事件。
如果不是,我们可以写一些东西来自动生成一段代码来引发PropertyChanged事件?
当前回答
在实现这些类型的属性时,你可能要考虑的其他事情是INotifyPropertyChang *ed *ing都使用事件参数类。
如果要设置大量的属性,那么事件参数类实例的数量可能非常大,您应该考虑缓存它们,因为它们是可能发生字符串爆炸的区域之一。
看一下这个实现,并解释为什么要考虑它。
Josh Smiths博客
其他回答
看这里:http://dotnet-forum.de/blogs/thearchitect/archive/2012/11/01/die-optimale-implementierung-des-inotifypropertychanged-interfaces.aspx
它是用德语写的,但你可以下载ViewModelBase.cs。cs-File中的所有注释都是用英语写的。
使用这个ViewModelBase-Class,可以实现类似于众所周知的依赖属性的可绑定属性:
public string SomeProperty
{
get { return GetValue( () => SomeProperty ); }
set { SetValue( () => SomeProperty, value ); }
}
=>这里我的解决方案具有以下特征
public ResourceStatus Status
{
get { return _status; }
set
{
_status = value;
Notify(Npcea.Status,Npcea.Comments);
}
}
没有refelction 短的符号 业务代码中没有神奇的字符串 PropertyChangedEventArgs在应用程序中的可重用性 在一条语句中通知多个属性的可能性
我在我的基本库中创建了一个扩展方法用于重用:
public static class INotifyPropertyChangedExtensions
{
public static bool SetPropertyAndNotify<T>(this INotifyPropertyChanged sender,
PropertyChangedEventHandler handler, ref T field, T value,
[CallerMemberName] string propertyName = "",
EqualityComparer<T> equalityComparer = null)
{
bool rtn = false;
var eqComp = equalityComparer ?? EqualityComparer<T>.Default;
if (!eqComp.Equals(field,value))
{
field = value;
rtn = true;
if (handler != null)
{
var args = new PropertyChangedEventArgs(propertyName);
handler(sender, args);
}
}
return rtn;
}
}
这适用于. net 4.5,因为有CallerMemberNameAttribute。 如果你想在一个早期的。net版本中使用它,你必须改变方法声明:…,[CallerMemberName] string propertyName = "",………,字符串propertyName…
用法:
public class Dog : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string _name;
public string Name
{
get { return _name; }
set
{
this.SetPropertyAndNotify(PropertyChanged, ref _name, value);
}
}
}
虽然显然有很多方法可以做到这一点,但除了AOP的神奇答案之外,没有一种答案似乎是在没有本地字段可以引用的情况下,直接从视图模型设置Model的属性。
问题是不能引用属性。但是,您可以使用Action来设置该属性。
protected bool TrySetProperty<T>(Action<T> property, T newValue, T oldValue, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(oldValue, newValue))
{
return false;
}
property(newValue);
RaisePropertyChanged(propertyName);
return true;
}
这可以像下面的代码摘录一样使用。
public int Prop {
get => model.Prop;
set => TrySetProperty(x => model.Prop = x, value, model.Prop);
}
查看这个BitBucket repo,了解该方法的完整实现,以及实现相同结果的几种不同方法,包括使用LINQ的方法和使用反射的方法。请注意,这些方法的性能较慢。
我建议使用ReactiveProperty。 这是除了Fody之外最短的方法。
public class Data : INotifyPropertyChanged
{
// boiler-plate
...
// props
private string name;
public string Name
{
get { return name; }
set { SetField(ref name, value, "Name"); }
}
}
而不是
public class Data
{
// Don't need boiler-plate and INotifyPropertyChanged
// props
public ReactiveProperty<string> Name { get; } = new ReactiveProperty<string>();
}
(文档)