2009-12-28 3 views
3

У меня есть ситуации, когда у меня есть несколько переменных, которые ЦЕННОСТИ зависят друг от друга, как это:PropertyChanged влияет на некоторые свойства

А функция B и C B является функцией A и C C является функцией от A и B

Любое значение может изменяться в пользовательском интерфейсе. Я делаю уведомление расчета и изменения, как это:

private string _valA; 
private string _valB; 
private string _valC; 

public string ValA 
{ 
    get { return _valA; } 
    set 
    { 
     if (_valA != value) 
     { 
      _valA = value; 
      RecalculateValues("ValA");  //Here ValB and ValC are calculated 
      OnPropertyChanged("ValA"); 
     } 
    } 
} 

public string ValB 
{ 
    get { return _valB; } 
    set 
    { 
     if (_valB != value) 
     { 
      _valB = value; 
      RecalculateValues("ValB");  //Here ValA and ValC are calculated 
      OnPropertyChanged("ValB"); 
     } 
    } 
} 

(...) 

private void RecalculateValues(string PropName) 
{ 
    if (PropName == "ValA") 
    { 
     _valB = TotalValue * _valA; 
     OnPropertyChanged("ValB"); 

     _valC = something * _valA 
     OnPropertyChanged("ValC"); 
    } 
    else 
    (...) 

} 

Я вызываю метод расчета на сеттера измененной переменной, вычисление значения для _valB, _valC (например), а затем вызвать PropertyChanged для вот эти. Я делаю это так из-за зависимостей между переменными, например, я могу контролировать, какая переменная вычисляется с правильными значениями. Я также подумал о запуске PropertyChanged для других переменных и выполнить вычисления на получателе переменных, но мне нужно было бы знать, какое свойство было изменено до этого и использовать это значение ... не уверен, что это лучшее/самое простое решение.

Это хороший способ сделать это? Мне не нравится идея выполнить это в блоке setter, но в то время я не вижу лучшего способа сделать это. Вы видите любое другое (лучшее или более чистое решение)?

Еще одна проблема, с которой я столкнулся, заключается в использовании IdataErrorInfo для проверки/представления информации об ошибках в пользовательском интерфейсе. Дело в том, что этот индексщик [columnName] вызывается в конце сеттера, и мне нужно было проверить значения перед вычислением, поэтому что если введенное значение недействительно, расчет не произойдет. Я всерьез подумываю о том, чтобы отказаться от IDataErrorInfo и просто вызвать метод проверки до того, как произойдет расчет (ы). Есть ли способ явно называть это или сразу после присвоения ценности?

ПРИМЕЧАНИЕ: ValidationRules не являются опцией, потому что мне нужно вызвать логику проверки на другом объекте из моего ViewModel.

+0

У вас есть '_valA' и т. Д., Введенные как строки, но вы выполняете« умножение »на строках, как в' _valB = TotalValue * _valA'. Пожалуйста, объясни. – jason

ответ

2

Его можно назвать вашей валидацией и расчетами в сеттере, если она не блокирует поток и переходит в интенсивные вычисления интенсивного процессора. Если у вас есть простые от 5 до 10 математических утверждений без привлечения сложных циклов, все в порядке.

Для привязки данных и WPF это единственный способ. Однако есть еще одна реализация, называемая IEditableObject, которая имеет BeginEdit, CancelEdit и EndEdit, где вы можете выполнять вычисления и проверку на функции «EndEdit».

В BeginEdit вы можете сохранить все значения в хранилище temp, в CancelEdit вы можете вернуть все значения из temp и Fire PropertyChaged для всех значений, которые были изменены, и в EndEdit вы можете, наконец, обновить все переменные и запустить PropertyChanged для всех тех, которые обновляются.

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

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

1

Поскольку вы можете вызвать NotifyPropertyChanged из любого места в классе, одним из способов упрощения этого является использование метода Calculate для NotifyPropertyChanged для всех трех переменных. Я использую этот трюк, когда у меня сложные вычисления с мультизависимостью.Иногда вы все равно хотите запустить событие в Setter: в этом случае я использую поле флага для отключения события, когда я обновляю свойство из вычислений, чтобы событие не запускалось дважды.