我的视图模型具有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);
}
}
答案 0 :(得分:6)
ValidationRules
不支持在设置另一个属性时使一个属性无效。
您应该做的是在视图模型中实现INotifyDataErrorInfo
,并在每次刷新属性的验证状态时引发ErrorsChanged
事件。
this TechNet article中提供了一个示例。