Я пытаюсь обновить свойство на основе значения двух других свойств.
Я использую INotifyPropertyChanged
здесь.
Итак, в основном у меня есть 3 свойства A
, B
и C
. Свойство, которое я обновляю, находится здесь C
на основе A
и B
. Я могу обновить значение свойства C
из A
и B
. Таким образом, свойство C
будет добавлением свойств A
и B
(C = A + B). Он отлично работает, когда одно значение передается либо из A
, либо из B
, но когда передаются значения из обоих свойств, оно принимает значение только из последнего переданного значения свойства. Я знаю, что мне нужно увеличивать значение C
при передаче значения из каждого свойства. Но как лучше всего этого добиться?
Вот мой код:
private int? _a;
public int? A
{
get => _a;
set
{
_a = value;
OnPropertyChanged($"A");
C = _a;
}
}
private int? _b;
public int? B
{
get => _b;
set
{
_b = value;
OnPropertyChanged($"B");
C = _b;
}
}
private int? _c;
public int? C
{
get => _c;
set
{
_c = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Обновлять
Извините за путаницу выше, в основном я пытаюсь обновить значение свойства C
, когда свойства A
и B
передаются. Таким образом, свойство C
будет добавлением свойств A
и B
(C = A + B). Надеюсь, это устранит путаницу?
Ваш пример кода не имеет никакого смысла. C ВСЕГДА является значением A или B (в зависимости от того, что было обновлено последним). Что вы хотите с этим делать?
Например, если C всегда должен быть суммой A и B, то в установщиках для A и Б, обоих из них, добавьте следующее: C = A + B;
Если это произведение, C = A * B;
И установщик C должен вызвать OnPropertyChanged("C");
Извините за путаницу, ребята, конечным результатом является обновление значения C
на основе значений как из A
, так и из B
.
«На основе значений как A
, так и B
»… что означает «на основе»? Добавлять? вычесть? умножить?
@JuanR Да добавлены значения A и B
@Kevin Пожалуйста, обновите свой вопрос, чтобы в нем говорилось, что вы на самом деле пытаетесь сделать.
Разве вы не можете просто получить C
собственность return _a + _b
? Цель (или проблема) до сих пор не ясна.
Учитывая приведенное выше пояснение, вы бы сделали что-то вроде:
private int? _a;
public int? A
{
get => _a;
set
{
if (value.HasValue != _a.HasValue || value.GetValueOrDefault(0) != _a.GetValueOrDefault(0))
{
_a = value;
OnPropertyChanged();
OnPropertyChanged(nameof(C));
}
}
}
private int? _b;
public int? B
{
get => _b;
set
{
if (value.HasValue != _b.HasValue || value.GetValueOrDefault(0) != _b.GetValueOrDefault(0))
{
_a = value;
OnPropertyChanged();
OnPropertyChanged(nameof(C));
}
}
}
public int? C
{
get => A + B;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Или используйте OnPropertyChanged(nameof(C));
Это, безусловно, делает код чище (и упрощает рефакторинг).
@stuartd просто опередил меня :)
Спасибо @SteveTodd за решение. Это имеет так много смысла сейчас. Я запутался в том, где на самом деле вызывать событие OnPropertyChanged?! Думаю, нужно вернуться и прочитать больше о INotifyPropertyChanged
. Также спасибо @Ed Plunkett за помощь в прояснении вопроса :)
@Kevin Вы просто хотите убедиться, что OnPropertyChanged(nameof(C))
вызывается всякий раз, когда значение C изменяется. Итак, выясните, что вызывает изменение значения C, и поместите его туда. Если у C есть установщик, вызовите OnPropertyChanged(nameof(C))
в установщике внутри оператора if, который показал вам Стив (и никогда не устанавливайте _c
вне этого установщика). Если C => A + B;
, то установщики A и B изменят значение C, поэтому вы хотите поместить OnPropertyChanged(nameof(C))
в оба этих установщика.
@Ed, подсказка параметра [CallerMemberName] в OnPropertyChanged автоматически заполняет имя функции/свойства, вызвавшее изменение, поэтому установщику для C (если он существует) не нужен бит nameof (вы, вероятно, знаете это, но для OP выгода).
Почему свойства дважды вызывают OnPropertyChanged
и есть ли причина использовать геттеры для A
и B
, когда базовые свойства доступны внутри?
@JuanR, считается плохой практикой прямой доступ к резервной переменной где-то, кроме ее геттера и сеттера. Что, если изменить код, чтобы инициировать другие действия при чтении или изменении значения? Два вызова должны сначала сказать, что «это свойство изменилось», а затем «это другое свойство, которое зависит от этого значения, также должно быть изменено».
@SteveTodd: я могу понять, считается ли это «плохой практикой», но я с уважением не согласен с этим. Класс выполняет внутренние операции, поэтому, по крайней мере, для меня он должен работать с резервным полем, а не с оболочкой, но это только мое предпочтение. Я не знаю о двойных звонках OnPropertyChanged
. Я понимаю, почему, но для меня это своего рода запах кода, когда свойство отвечает за инициирование событий для какого-то другого свойства. Возможно, C
должен быть методом?
@JuanR, что, если вы хотите привязать вычисленный результат к своей форме? Форма должна знать, что она изменилась, и она должна быть чем-то, что можно связать.
@SteveTodd: я думаю, что потребности вашей формы (GUI) не должны иметь никакого отношения к дизайну вашего класса. В любом случае, давайте не будем загрязнять этот ответ философскими разногласиями. Мы представили ОП разные точки зрения. Ему решать. :-)
Если вы присвоите x ряд значений, x всегда будет иметь последнее назначенное значение. C должен быть рассчитан или что-то в этом роде? Вы говорите: «Я знаю, что мне нужно увеличивать значение C при передаче значения из каждого свойства». -- затем напишите код, который будет увеличивать значение C "при передаче значения из каждого свойства" (мы не можем помочь вам с этой частью в кавычках, потому что мы не знаем, что это значит). Какие бы вычисления ни выполнялись для определения значения C, когда C необходимо обновить, выполняйте их каждый раз, когда результат этих вычислений изменится.