Может быть, здесь уже такой вопрос, но я его не нашел.Self-subscribe to PropertyChanged или метод добавления метода в setter?
У меня есть приложение MVVM, и в моем ViewModel
я должен выполнить некоторые дополнительные действия по изменению некоторых свойств (например, если View
меняет их). Какой подход лучше на ваш взгляд и почему?
первый - Добавить 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();
}
}
}
второй - Self подписаться на 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 объектов. Это просто View и ViewModel. Что лучше? Первый код «меньше» и имеет меньше накладных расходов, но второй (на мой взгляд) более ясен, и я могу использовать фрагменты кода для кода свойств автогенерации. Даже больше - во 2-м случае я могу написать в обработчик события что-то вроде:
On.PropertyChanged(e, p => p.MyProperty, AdditionalAction);
где On
является класс-хелпер.
Итак, что лучше на вашем уме и почему?
ОБНОВЛЕНО:
ОК, похоже, я нашел еще один подход:
3rd - добавить "точку расширения" в 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();
}
}
Этот путь мы не используем событие, но все «дополнительные действия» вызываются из одной и той же «точки расширения». Является ли «одно место для всех дополнительных действий» лучше, чем «непрозрачный рабочий процесс»?
http://tergiver.wordpress.com/2011/01/20/self-subscription-is-asinine/ – Tergiver
Sidenote: рассмотреть возможность использования вспомогательного метода, чтобы поместить три строки в инкубаторе ваших свойств к одному, возвращая логическое значение, если свойство изменилось. Сокращение и отсутствие дублирования. например 'if (RaisePropertyChanged (ref _MyProperty, value, o => o.MyProperty)) AdditionalAction();' – stijn
@Тергивер, в чем разница между вашим путем и моим вторым способом? Они одинаковые - вы пишете дополнительный код не в «сеттере», а в «обработчике событий» - метод «OnXXX» с этой точки зрения совпадает с самоподпиской на событие. Итак, с моей точки зрения, мой вопрос: «Лучше ли вызывать« AdditionalAction »из сеттера или из метода OnPropertyChanged?» (даже если на самом деле нет метода OnPropertyChanged) – chopikadze