У меня есть модель представления с 2 свойствами: A
и B
, и я хочу проверить это A < B
.
Ниже представлена моя упрощенная реализация, в которой я использую пользовательское правило проверки. Поскольку каждое свойство проверяется независимо, это приводит к неприятной проблеме: если введенное значение A
недопустимо, оно остается таким даже после изменения B
, поскольку проверка B
ничего не знает о A
.
Это можно увидеть на этой демонстрации:
A
недопустимо после ввода 11
, это правильно, так как 11 > 2
. Изменение B
на 22
не переоценивает A
, мне нужно отредактировать A
, чтобы пройти проверку.
Что я хочу? Я хочу, чтобы после включения 22
в B
красная граница (ошибка проверки) исчезла, и A = 11, B = 22
были бы исходными значениями в модели представления.
Как я могу в B
проверке каким-либо образом заставить A
проверка после нового B
значение синхронизируется с источником?
Просмотр модели:
public class ViewModel : INotifyPropertyChanged
{
int _a;
public int A
{
get => _a;
set
{
_a = value;
OnPropertyChanged();
}
}
int _b;
public int B
{
get => _b;
set
{
_b = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public virtual void OnPropertyChanged([CallerMemberName] string property = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
Просмотр:
<StackPanel>
<TextBox Margin="10" Text="{local:MyBinding A}" />
<TextBox Margin="10" Text="{local:MyBinding B}" />
</StackPanel>
Просмотр кода:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel { A = 1, B = 2 };
}
Связывание:
public class MyBinding : Binding
{
public MyBinding(string path) : base(path)
{
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
ValidationRules.Add(new MyValidationRule());
}
}
Правило проверки:
public class MyValidationRule : ValidationRule
{
public MyValidationRule() : base(ValidationStep.ConvertedProposedValue, false) { }
public override ValidationResult Validate(object value, CultureInfo cultureInfo) => ValidationResult.ValidResult; // not used
public override ValidationResult Validate(object value, CultureInfo cultureInfo, BindingExpressionBase owner)
{
var binding = owner as BindingExpression;
var vm = binding?.DataItem as ViewModel;
switch (binding.ResolvedSourcePropertyName)
{
case nameof(vm.A):
if ((int)value >= vm.B)
return new ValidationResult(false, "A should be smaller than B");
break;
case nameof(vm.B):
if ((int)value <= vm.A)
return new ValidationResult(false, "B should be bigger than A");
break;
}
return base.Validate(value, cultureInfo, owner);
}
}