Tengo un modelo de vista con 2 propiedades: Ay Bquiero validar eso A < B.
A continuación se muestra mi implementación simplificada donde uso la regla de validación personalizada. Dado que cada propiedad se valida de forma independiente, conduce a un problema molesto: si el Avalor ingresado no es válido, entonces permanece así incluso después de cambiar B, ya que la validación de Bno sabe nada A.
Esto se puede ver en esta demostración:
Aes inválido después de ingresar 11, eso es correcto desde entonces 11 > 2. Cambiar Ba 22no volver a evaluar A, tengo que editar Apara que se apruebe la validación.
¿Lo que quiero? Quiero que después de entrar 22en Bel borde rojo (error de validación) desaparezca y A = 11, B = 22que sean valores de origen en el modelo de vista.
¿Cómo puedo en la Bvalidación forzar de alguna manera la Avalidación después de que el nuevo Bvalor se sincronice con la fuente?
Ver modelo:
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));
}
Ver:
<StackPanel>
<TextBox Margin="10" Text="{local:MyBinding A}" />
<TextBox Margin="10" Text="{local:MyBinding B}" />
</StackPanel>
Ver código:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel { A = 1, B = 2 };
}
Unión:
public class MyBinding : Binding
{
public MyBinding(string path) : base(path)
{
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
ValidationRules.Add(new MyValidationRule());
}
}
Regla de validación:
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);
}
}
fuente


OnPropertyChanged(nameof(B))al setter de aA(y el equivalente para el setter deB)?INotifyDataErrorInfoen su modelo de vista si desea realizar este tipo de validación. No es compatible con las reglas de validación.A: antes o después de validarB(en otras palabras, antes de que el valor de B sea aceptado y sincronizado con la fuente o después). El orden importa. Y, de hecho, primero tengo que tener todos los valores modificados a mano y solo entonces hacer la validación en orden normal.Respuestas:
ValidationRulesno admite la invalidación de una propiedad al configurar otra propiedad.Lo que debe hacer es implementar
INotifyDataErrorInfoen su modelo de vista y generar elErrorsChangedevento cada vez que desee actualizar el estado de validación de una propiedad.Hay un ejemplo disponible en este artículo de TechNet .
fuente