Ich habe View - Modell mit 2 Eigenschaften: A
und B
und ich möchte , dass validieren A < B
.
Unten ist meine vereinfachte Implementierung, bei der ich eine benutzerdefinierte Validierungsregel verwende. Da jede Eigenschaft unabhängig validiert wird, führt dies zu einem ärgerlichen Problem: Wenn der eingegebene A
Wert ungültig ist, bleibt dies auch nach einer Änderung so B
, da die Validierung von B
nichts weiß A
.
Dies ist auf dieser Demo zu sehen:
A
ist nach der Eingabe ungültig 11
, das ist da richtig 11 > 2
. Ändern B
zu 22
nicht wieder evalute A
, habe ich zu bearbeiten A
Validierung bestanden zu haben.
Was ich möchte? Ich möchte, dass nach dem Eintreten 22
in B
den roten Rand (Validierungsfehler) verschwindet und Quellwerte A = 11, B = 22
im Ansichtsmodell wären.
Wie kann ich bei der B
Validierung die Validierung erzwingen, A
nachdem der neue B
Wert mit der Quelle synchronisiert wurde?
Modell anzeigen:
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));
}
Aussicht:
<StackPanel>
<TextBox Margin="10" Text="{local:MyBinding A}" />
<TextBox Margin="10" Text="{local:MyBinding B}" />
</StackPanel>
Code anzeigen:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel { A = 1, B = 2 };
}
Bindung:
public class MyBinding : Binding
{
public MyBinding(string path) : base(path)
{
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
ValidationRules.Add(new MyValidationRule());
}
}
Validierungsregel:
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);
}
}
INotifyDataErrorInfo
in Ihrem Ansichtsmodell implementieren, wenn Sie diese Art der Validierung durchführen möchten. Es wird nicht von Validierungsregeln unterstützt.
A
: vor oder nach der Validierung B
(mit anderen Worten, bevor der Wert von B akzeptiert und mit der Quelle oder danach synchronisiert wird). Bestellangelegenheit. Und tatsächlich muss ich zuerst alle geänderten Werte zur Hand haben und erst dann die Validierung in normaler Reihenfolge durchführen.
OnPropertyChanged(nameof(B))
den Setter von a aufrufenA
(und das Äquivalent für den Setter vonB
)?