当房产价值发生变化时,举起一个活动?

时间:2010-02-11 18:40:19

标签: c# .net events properties

有一个属性,名为 ImageFullPath1

public string ImageFullPath1 {get; set; }

每当它的值发生变化时,我都会触发一个事件。我知道要改变INotifyPropertyChanged,但我想用事件来做。

6 个答案:

答案 0 :(得分:147)

使用事件实现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;
}

请注意,这会做以下事情:

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

  • 在尝试调用之前制作PropertyChanged代理的副本(未能执行此操作会产生竞争条件)。

  • 正确实施INotifyPropertyChanged界面。

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

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

public event EventHandler ImageFullPathChanged;

然后在第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();
            }
        }
    }

答案 1 :(得分:33)

我使用与Aaronaught大致相同的模式,但是如果你有很多属性,那么使用一些通用方法魔术来使你的代码多一点DRY

可能会更好
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
}

通常我也将OnPropertyChanged方法设为虚拟,以允许子类覆盖它以捕获属性更改。

答案 2 :(得分:7)

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

答案 3 :(得分: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*/);
    }
}                        

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

答案 4 :(得分:4)

如果您将属性更改为使用支持字段(而不是自动属性),则可以执行以下操作:

public event EventHandler ImageFullPath1Changed;
private string _imageFullPath1 = string.Empty;

public string ImageFullPath1 
{
  get
  {
    return imageFullPath1 ;
  }
  set
  {
    if (_imageFullPath1 != value)
    { 
      _imageFullPath1 = value;

      EventHandler handler = ImageFullPathChanged;
      if (handler != null)
        handler(this, e);
    }
  }
}

答案 5 :(得分:0)

已经有很好的答案了,但还是有一些人一头雾水

  • EventArgs 以及他们可以使用它的人
  • 其中一些是关于如何传递自定义参数
class Program
    {
        static void Main(string[] args)
        {
            Location loc = new Location();

            loc.LocationChanged += (obj, chngLoc) =>
            {
                Console.WriteLine("Your LocId Is");
                Console.WriteLine(chngLoc.LocId);
                Console.WriteLine(chngLoc.LocCode);
                Console.WriteLine(chngLoc.LocName);
                Console.ReadLine();
            };

            Console.WriteLine("Default Location Is");
            Console.WriteLine(loc.LocId);

            Console.WriteLine("Change Location");
            loc.LocId = Console.ReadLine();
        }
    }

    public class Location
    {

        private string _locId = "Default Location";
        public string LocId
        {
            get
            {
                return _locId;
            }
            set
            {

                _locId = value;
                if (LocationChanged != null && value != LocId)
                {
                    B1Events b1 = new B1Events();
                    b1.LocCode = "Changed LocCode";
                    b1.LocId = value;
                    b1.LocName = "Changed LocName";
                    LocationChanged(this, b1);
                }
                
            }
        }
         public event EventHandler<B1Events> LocationChanged;
    }

    public class B1Events : EventArgs
    {
        public string LocId { get; set; }
        public string LocCode{ get; set; }
        public string LocName { get; set; }
    }