微软应该为INotifyPropertyChanged实现一些时髦的东西,就像在自动属性中,只需要指定{get;设置;通知;} 我认为这样做很有意义。或者做这个手术有什么并发症吗?

我们能在属性中实现类似notify的东西吗。在你的类中实现INotifyPropertyChanged是否有一个优雅的解决方案,或者唯一的方法是在每个属性中引发PropertyChanged事件。

如果不是,我们可以写一些东西来自动生成一段代码来引发PropertyChanged事件?


当前回答

从。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)

其他回答

我写了一篇文章来帮助你(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)
}

好处:

基类是可选的 没有对每个“设定值”进行反思 可以具有依赖于其他属性的属性,并且它们都自动引发适当的事件(本文有一个这样的示例)

如果你在。net 4.5中使用动态,你不需要担心INotifyPropertyChanged。

dynamic obj = new ExpandoObject();
obj.Name = "John";

如果Name被绑定到某个控件,它就可以正常工作。

另一个组合解决方案是使用StackFrame:

public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void Set<T>(ref T field, T value)
    {
        MethodBase method = new StackFrame(1).GetMethod();
        field = value;
        Raise(method.Name.Substring(4));
    }

    protected void Raise(string propertyName)
    {
        var temp = PropertyChanged;
        if (temp != null)
        {
            temp(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

用法:

public class TempVM : BaseViewModel
{
    private int _intP;
    public int IntP
    {
        get { return _intP; }
        set { Set<int>(ref _intP, value); }
    }
}

我正在编写一个处理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)