只要房产价值发生变化,就举起活动?

Moh*_*yan 62 .net c# events properties

有一个属性,它名为ImageFullPath1

public string ImageFullPath1 {get; set; }
Run Code Online (Sandbox Code Playgroud)

每当它的值发生变化时,我都会开火.我知道要改变INotifyPropertyChanged,但我想用事件来做.

Aar*_*ght 151

INotifyPropertyChanged接口与事件实现.该界面只有一个成员,PropertyChanged这是消费者可以订阅的事件.

Richard发布的版本不安全.以下是如何安全地实现此接口:

public class MyClass : INotifyPropertyChanged
{
    private string imageFullPath;

    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, e);
    }

    protected void OnPropertyChanged(string propertyName)
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    public string ImageFullPath
    {
        get { return imageFullPath; }
        set
        {
            if (value != imageFullPath)
            {
                imageFullPath = value;
                OnPropertyChanged("ImageFullPath");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这会执行以下操作:

  • 摘要属性更改通知方法,以便您可以轻松地将其应用于其他属性;

  • 尝试调用PropertyChanged委托之前制作委托的副本(未能执行此操作将创建竞争条件).

  • 正确实现INotifyPropertyChanged界面.

如果要另外为要更改的特定属性创建通知,可以添加以下代码:

protected void OnImageFullPathChanged(EventArgs e)
{
    EventHandler handler = ImageFullPathChanged;
    if (handler != null)
        handler(this, e);
}

public event EventHandler ImageFullPathChanged;
Run Code Online (Sandbox Code Playgroud)

然后在行OnImageFullPathChanged(EventArgs.Empty)后添加行OnPropertyChanged("ImageFullPath").

由于我们有.Net 4.5 CallerMemberAttribute,它存在,它允许在源代码中删除属性名称的硬编码字符串:

    protected void OnPropertyChanged(
        [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    public string ImageFullPath
    {
        get { return imageFullPath; }
        set
        {
            if (value != imageFullPath)
            {
                imageFullPath = value;
                OnPropertyChanged();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 到目前为止,成为此线程中唯一的人才能获得对事件的空检查. (25认同)
  • 我会将来自`OnPropertyChanged("ImageFullPath");` 的调用替换为`nameof(ImageFullPath)`。通过这种方式,您将在编译时检查属性的名称,以便在您更改它的情况下,如果您忘记在方法调用中替换它,您将收到一条错误消息。 (4认同)

Mik*_*erg 35

我使用与Aaronaught大致相同的模式,但是如果你有很多属性,那么使用一些通用方法魔法来使你的代码更加干燥可能会更好

public class TheClass : INotifyPropertyChanged {
    private int _property1;
    private string _property2;
    private double _property3;

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) {
        PropertyChangedEventHandler handler = PropertyChanged;
        if(handler != null) {
            handler(this, e);
        }
    }

    protected void SetPropertyField<T>(string propertyName, ref T field, T newValue) {
        if(!EqualityComparer<T>.Default.Equals(field, newValue)) {
            field = newValue;
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }

    public int Property1 {
        get { return _property1; }
        set { SetPropertyField("Property1", ref _property1, value); }
    }
    public string Property2 {
        get { return _property2; }
        set { SetPropertyField("Property2", ref _property2, value); }
    }
    public double Property3 {
        get { return _property3; }
        set { SetPropertyField("Property3", ref _property3, value); }
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

通常我也会将OnPropertyChanged方法设置为virtual,以允许子类覆盖它以捕获属性更改.

  • 现在使用.NET 4.5,您甚至可以使用CallerMemberNameAttribute http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx免费获取属性名称. (11认同)

Rya*_*ner 7

在属性更改时引发事件正是INotifyPropertyChanged所做的事情.有一个必需的成员来实现INotifyPropertyChanged,那就是PropertyChanged事件.您自己实现的任何内容都可能与该实现相同,因此不使用它没有任何优势.

  • +1为真相.即使你想为每个属性实现一个单独的`XChangedEvent`,你也已经开始工作了,所以继续实现INotifyPropertyChanged.未来(如WPF)会感谢你,因为这是未来的期望. (2认同)

Ric*_*erg 5

public event EventHandler ImageFullPath1Changed;

public string ImageFullPath1
{
    get
    {
        // insert getter logic
    }
    set
    {
        // insert setter logic       

        // EDIT -- this example is not thread safe -- do not use in production code
        if (ImageFullPath1Changed != null && value != _backingField)
            ImageFullPath1Changed(this, new EventArgs(/*whatever*/);
    }
}                        
Run Code Online (Sandbox Code Playgroud)

那就是说,我完全赞同瑞恩.这种情况正是INotifyPropertyChanged存在的原因.

  • 此事件调用具有竞争条件.在检查和后续调用之间,`ImageFullPath1Changed`的值可以更改为`null`.不要调用这样的事件! (3认同)
  • 检查ImageFullPath1Changed事件的null是不安全的.鉴于事件可以从类外部异步订阅/取消订阅,在null检查后它可能变为null并导致NullReferenceException.相反,您应该在检查null之前获取本地副本.见Aaronaught的回答. (2认同)