Самостоятельно подписаться на вызов метода PropertyChanged или addition в setter?



Может быть, здесь уже есть такой вопрос, но я его не нашел.



У меня есть приложение MVVM, и в моем ViewModel я должен делать некоторые дополнительные действия по изменению некоторых свойств (например, если View изменяет их). Какой подход лучше на ваш взгляд и почему?



1-й-добавить AdditionalAction вызов сеттера



public class ViewModel: INotifyPropertyChanged
{
private int _MyProperty;

public int MyProperty
{
get { return _MyProperty; }
set
{
if (_MyProperty == value) return;
_MyProperty = value;
RaisePropertyChanged(() => MyProperty);

// --- ADDITIONAL CODE ---
AdditionalAction();
}
}
}


2-я-самостоятельная подписка на INotifyPropertyChanged



public class ViewModel: INotifyPropertyChanged
{
public ViewModel()
{
// --- ADDITIONAL CODE ---
PropertyChanged += OnPropertyChanged;
}

private int _MyProperty;

public int MyProperty
{
get { return _MyProperty; }
set
{
if (_MyProperty == value) return;
_MyProperty = value;
RaisePropertyChanged(() => MyProperty);
}
}

void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
// --- ADDITIONAL CODE ---
if (e.PropertyName == "MyProperty")
AdditionalAction();
}
}


Представьте, что у меня нет проблем с производительностью или 10 000 объектов. Это просто вид и модель вида. Что может быть лучше? Первый код "меньше" и имеет меньше накладных расходов, но второй (на мой взгляд) более понятен, и я могу использовать фрагменты кода для автоматической генерации кода свойств. Даже больше - во 2-м случае я могу написать в обработчике событий что-то вроде:



On.PropertyChanged(e, p => p.MyProperty, AdditionalAction);


Где On-класс-помощник.



Итак, что у вас на уме лучше и почему?

Обновлено:



Ладно, похоже, я нашел еще одного подход:



3-й-добавить "точку расширения" в RaisePropertyChanged:



public class NotificationObject : INotifyPropertyChanged
{
void RaisePropertyChanged(Expression<...> property)
{
// ... Raise PropertyChanged event
if (PropertyChanged != null)
// blah-blah

// Call extension point
OnPropertyChanged(property.Name);
}

public virtual OnPropertyChanged(string propertyName)
{
}
}

public class ViewModel: NotificationObject
{
private int _MyProperty;

public int MyProperty
{
get { return _MyProperty; }
set
{
if (_MyProperty == value) return;
_MyProperty = value;
RaisePropertyChanged(() => MyProperty);
}
}

override OnPropertyChanged(string propertyName)
{
if (propertyName == "MyProperty")
AdditionalAction();
}
}


Таким образом, мы не используем событие, но все" дополнительные действия "вызываются из одной и той же"точки расширения". Является ли "одно место для всех действий добавления" лучше ,чем"непрозрачный рабочий процесс"?

562   2  

2 ответов:

Я бы определенно выбрал первый метод:

  • все ясно
  • он явен в своем потоке и намерении
  • это позволяет избежать странной (imo) самостоятельной подписки

"преимущества" второго, который позволяет использовать автогенерированные свойства, не стоит ясности потока выполнения первого случая, imo.

Надеюсь, это поможет.

Вот "обычный" паттерн. Это позволяет поместить специфичный для свойств код внутри метода OnX и позволяет производным классам делать то же самое. Нет необходимости в большом операторе switch, если, конечно, вы не являетесь внешним слушателем, но это нормально для курса INotifyPropertyChanged.

public class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void FirePropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
            handler(this, e);
    }
}

public class ViewModel : NotificationObject
{
    private int _MyProperty1;
    public int MyProperty1
    {
        get { return _MyProperty1; }
        set
        {
            if (value != _MyProperty1)
            {
                _MyProperty1 = value;
                OnMyProperty1Changed(new PropertyChangedEventArgs("MyProperty1"));
            }
        }
    }

    protected virtual void OnMyProperty1Changed(PropertyChangedEventArgs e)
    {
        FirePropertyChanged(e);
    }

    private int _MyProperty2;
    public int MyProperty2
    {
        get { return _MyProperty2; }
        set
        {
            if (value != _MyProperty2)
            {
                _MyProperty2 = value;
                OnMyProperty2Changed(new PropertyChangedEventArgs("MyProperty2"));
            }
        }
    }

    protected virtual void OnMyProperty2Changed(PropertyChangedEventArgs e)
    {
        FirePropertyChanged(e);
    }
}

Comments

    Ничего не найдено.