微软应该为INotifyPropertyChanged实现一些时髦的东西,就像在自动属性中,只需要指定{get;设置;通知;} 我认为这样做很有意义。或者做这个手术有什么并发症吗?
我们能在属性中实现类似notify的东西吗。在你的类中实现INotifyPropertyChanged是否有一个优雅的解决方案,或者唯一的方法是在每个属性中引发PropertyChanged事件。
如果不是,我们可以写一些东西来自动生成一段代码来引发PropertyChanged事件?
微软应该为INotifyPropertyChanged实现一些时髦的东西,就像在自动属性中,只需要指定{get;设置;通知;} 我认为这样做很有意义。或者做这个手术有什么并发症吗?
我们能在属性中实现类似notify的东西吗。在你的类中实现INotifyPropertyChanged是否有一个优雅的解决方案,或者唯一的方法是在每个属性中引发PropertyChanged事件。
如果不是,我们可以写一些东西来自动生成一段代码来引发PropertyChanged事件?
当前回答
我正在编写一个处理INotifyPropertyChanged的库,主要思想是使用动态代理来通知更改。
回购在这里:CaulyKan/NoMorePropertyChanged
使用这个库,你可以写:
public dynamic Test1Binding { get; set; }
public TestDTO Test1
{
get { return (TestDTO)Test1Binding; }
set { SetBinding(nameof(Test1Binding), value); }
}
然后将所有绑定和修改转到Test1Binding,无论TestDTO有多复杂,它都会自动通知PropertyChange和CollectionChanged。
它还可以处理依赖关系。
[DependsOn("Test1Binding.TestString")]
public string Test2
{
get { return Test1Binding.TestString; }
}
请给我一些建议。
其他回答
从。net 4.5开始,终于有了一个简单的方法。
. net 4.5引入了一个新的调用者信息属性。
private void OnPropertyChanged<T>([CallerMemberName]string caller = null) {
// make sure only to call this if the value actually changes
var handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(caller));
}
}
在函数中添加比较器可能也是一个好主意。
EqualityComparer<T>.Default.Equals
更多的例子在这里和这里
参见调用者信息(c#和Visual Basic)
这就是大规模的过度工程。这比仅仅以正确的方式进行要复杂得多,而且几乎没有任何好处。如果你的IDE支持代码片段(Visual Studio/MonoDevelop支持),那么你可以让这个实现变得非常简单。你需要输入的只是属性的类型和属性名。额外的三行代码将自动生成。
我在我的基本库中创建了一个扩展方法用于重用:
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);
}
}
}
还有Fody,它有一个AddINotifyPropertyChangedInterface插件,它让你这样写:
[AddINotifyPropertyChangedInterface]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
}
...并在编译时注入属性更改通知。
我写了一篇文章来帮助你(https://msdn.microsoft.com/magazine/mt736453)。你可以使用SolSoft。DataBinding NuGet包。然后你可以这样写代码:
public class TestViewModel : IRaisePropertyChanged
{
public TestViewModel()
{
this.m_nameProperty = new NotifyProperty<string>(this, nameof(Name), null);
}
private readonly NotifyProperty<string> m_nameProperty;
public string Name
{
get
{
return m_nameProperty.Value;
}
set
{
m_nameProperty.SetValue(value);
}
}
// Plus implement IRaisePropertyChanged (or extend BaseViewModel)
}
好处:
基类是可选的 没有对每个“设定值”进行反思 可以具有依赖于其他属性的属性,并且它们都自动引发适当的事件(本文有一个这样的示例)