私は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);
}
}
Validationruleは、単純なユースケースにのみ適しています。VM内のinotifydataerrorinfoは、実質的なものに対する通常のアプローチです。流暢な検証を見てください。イントロの例:gist.github.com/holymoo/11243164 fluentvalidation.net/built-in-validators オフハンド-両方のプロパティはおそらく同じルールを持ち、述語チェックで両方が良いでしょう。
—
アンディ
モデルを直接公開する場合のみ関連します。モデルを直接公開しないでください。viewmodelsを使用します。有効なデータのみをコミットします。
—
アンディ、
@Sinatr:「検証ルールの概念の方が正しいと思う」は誤りです。
—
mm8
INotifyDataErrorInfo
この種の検証を実行する場合は、ビューモデルに実装する必要があります。検証ルールではサポートされていません。
@Rekshino、そう、私はいつ検証
—
Sinatr
A
するかについても考えていました:検証の前または後B
(つまり、Bの値が受け入れられてソースと同期される前または後)。注文事項。実際、最初にすべての変更された値を手元に置いて、通常の順序で検証を実行する必要があります。
OnPropertyChanged(nameof(B))
aのセッターA
(およびのセッターの同等物B
)も呼び出す場合に機能しますか?