code

속성 값이 변경 될 때마다 이벤트를 발생합니까?

codestyles 2020. 11. 29. 11:42
반응형

속성 값이 변경 될 때마다 이벤트를 발생합니까?


속성이 있습니다. 이름은 ImageFullPath1입니다.

public string ImageFullPath1 {get; set; }

값이 변경 될 때마다 이벤트를 시작합니다. 변경하는 것을 알고 INotifyPropertyChanged있지만 이벤트로하고 싶습니다.


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();
            }
        }
    }

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
}

일반적으로 OnPropertyChanged 메서드를 가상으로 만들어 하위 클래스가 속성 변경 사항을 포착하도록 재정의 할 수 있도록합니다.


Raising an event when a property changes is precisely what INotifyPropertyChanged does. There's one required member to implement INotifyPropertyChanged and that is the PropertyChanged event. Anything you implemented yourself would probably be identical to that implementation, so there's no advantage to not using it.


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*/);
    }
}                        

That said, I completely agree with Ryan. This scenario is precisely why INotifyPropertyChanged exists.


If you change your property to use a backing field (instead of an automatic property), you can do the following:

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);
    }
  }
}

참고URL : https://stackoverflow.com/questions/2246777/raise-an-event-whenever-a-propertys-value-changed

반응형