Лучшие практики INotifyPropertyChanged

Когда у меня есть класс, реализующий INotifyPropertyChanged, можно ли раскрыть реализацию как общедоступный метод?

Например, если у меня есть свойство под названием «Сумма» в классе, и я хочу, чтобы щелчок кнопки в пользовательском интерфейсе обновлял сумму, как лучше всего это сделать?

Ниже приведен псевдокод, чтобы проиллюстрировать, что я имею в виду.

classinstance.NotifyPropertyChanged("Sum");
...
public Sum { 
   get { return x + y + z; }
}

person Jason    schedule 01.09.2011    source источник


Ответы (2)


В .Net предпочтительной практикой для методов, вызывающих события, является объявление метода защищенным, чтобы его могли вызывать только производные классы (это потому, что только класс, который объявляет событие, может вызвать его. событие от производного класса требуется метод, чтобы вызвать событие).

Например...

protected void OnPropertyChanged(string propertyName)
{
    var handler = this.PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Затем этот метод вызывается классом (или производными классами) в установщике свойств, чтобы указать, что свойство изменилось, например ...

public object MyProperty
{
    get { return _myProperty; }
    set
    {
        _myProperty = value;
        OnPropertyChanged("MyProperty");
    }
}

Затем другие объекты могут подписаться на это событие и будут получать уведомления при каждом изменении свойства MyProperty.

Теперь, чтобы ответить на ваш вопрос о том, может ли OnPropertyChanged метод быть общедоступным. Ответ - да, но вы должны спросить себя, почему это так.

Почему другой класс узнает об изменении свойства, чтобы он мог вызвать метод? если он уже «знает», когда свойство было изменено, вам не нужно в первую очередь подписываться на событие изменения свойства! Только сам класс должен «знать», когда одно из его собственных свойств изменилось.

В вашем примере вы уведомляете, что свойство «сумма» было изменено. но это не так. Фактически, ваш код даже не позволяет изменять это свойство за пределами его собственного класса.

Я подозреваю, что, возможно, вы хотите каким-то образом уведомить о том, что свойство sum необходимо переоценить, потому что зависимое свойство было изменено. В этом случае вам необходимо вызвать событие изменения свойства при изменении этого зависимого свойства.

Представьте, что изменения в свойстве MyProperty, показанные ранее, также означают, что Sum изменилась, и это будет обрабатываться следующим образом:

// This property is used by the 'sum' property so if this changes
// clients need to know that 'sum' has also changed.
public object MyProperty
{
    get { return _myProperty; }
    set
    {
        _myProperty = value;
        OnPropertyChanged("MyProperty");
        OnPropertyChanged("Sum");
    }
}
person Benjamin Gale    schedule 17.06.2012

что касается гораздо более красивой реализации базы:

    public abstract class NotificationObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged<T>(Expression<Func<T>> me)
            => RaisePropertyChanged((me.Body as MemberExpression)?.Member.Name);

        protected virtual void RaisePropertyChanged(string propertyName)
            => PropertyChanged?.Invoke(this, propertyName);
    }

Также стоит поискать https://msdn.microsoft.com/en-us/magazine/mt736453.aspx

person mdn    schedule 07.12.2018