Понятия не имею, почему при изменении других свойств вызывается несвязанное свойство, почему это так ...
Для класса Form1VM
каждое свойство не связано с другими, и вы также внедрили INotifyPropertyChanged
для предоставления уведомления об изменениях, поэтому вы ожидаете, что механизм привязки будет достаточно умен, чтобы извлекать только те значения, которые опубликовали изменение уведомление.
К сожалению, это не тот случай, и механизм по умолчанию извлекает все связанные свойства после того, как отправляет изменение в связанный элемент. Механизм по умолчанию контролирует, что событие INotifyPropertyChanged.PropertyChanged
отвечает, вытягивая все связанные значения вместо только измененного.
Все это обрабатывается PropertyManager , который поддерживается Свойство BindingContext элемента управления ContainerControl .
Наблюдаемое поведение выглядит как результат PropertyManager.OnCurrentChanged метода , который вызывает BindingManagerBase.PushData , что в конечном итоге приводит к итерации по привязкам и вызову Binding. PushData , где следующий код выполняется и извлекает значение источника данных.
if (IsBinding) {
dataSourceValue = bindToObject.GetValue();
object controlValue = FormatObject(dataSourceValue);
SetPropValue(controlValue);
modified = false;
}
Код субъекта объявляет привязку так, что вышеуказанная последовательность запускается событием TextBox.Validating
. Когда базовый источник данных (_vm
) вызывает событие PropertyChanged
, последовательность снова начинается с метода PropertyManager.OnCurrentChanged
.
как это предотвратить?
Вы можете создать производный класс PropertyManager
, который переопределяет метод OnCurrentChanged
и кодировать ваше собственное поведение. Чтобы использовать этот пользовательский класс, вам также необходимо создать пользовательский класс BindingContext для его установки. Это не то, что я бы порекомендовал, если вы можете принять один опрос связанных свойств для изменений, распространяемых механизмом привязки данных. Такое поведение может быть достигнуто путем использования BindingSource в качестве посредника между _vm
и привязкой.
Ниже показаны изменения в опубликованном коде, необходимые для использования BindingSource.
private BindingSource bs = new BindingSource();
public Form1()
{
InitializeComponent();
_vm = new Form1VM();
bs.DataSource = _vm;
}
private void BindControl(Control control, string propertyName)
{
control.DataBindings.Clear();
control.DataBindings.Add(nameof(control.Text), bs, propertyName, true, DataSourceUpdateMode.OnValidation);
}
Другая альтернатива для Form1VM
заключается в реализации интерфейса ICurrencyManagerProvider и предоставлении пользовательской реализации CurrencyManager Class , аналогичной тому, как это делает класс BindingSource. Это то, что я никогда не пытался, но я подозреваю, что это будет аналогично задаче создания собственного PropertyManager.