ValidationAttribute属性で入力値検証


はじめに

WPFにはDataAnnotationsという仕組みがあって、入力値の検証ができる属性が実装されています。プロパティに属性をつけて、ユーザー入力に対して検証ルールに合致しなければ、エラーを通知するというものです。本記事では、どんな検証ができるのか紹介します。

まずは、DataAnnotationsを参照設定に加えます。

using System.ComponentModel.DataAnnotations;

プロパティの定義と初期化

ReactivePropertyのSetValidateAttributeメソッドをつかいます。

public class SampleViewModel: ViewModelBase
{

    public SampleViewModel()
    {
        // ユーザーからの入力を受けるプロパティ
        this.Input = new ReactiveProperty<string>()
            .SetValidateAttribute(() => this.Input)
            .AddTo(this.disposedValue);
    }

    public ReactiveProperty<string> Input { get; }

}

さまざまな入力値検証

Required

必須入力。入力されているかどうかをチェックします。

[Required()]
public ReactiveProperty<string> Input { get; }

引数にErrorMessageを指定すれば、任意のメッセージを表示することができます。

[Required(ErrorMessage = "何か入力してください。")]
public ReactiveProperty<string> Input { get; }

StringLength

文字列長。引数に文字数を設定。入力値が設定した文字数以内かチェックします。

[StringLength(10)]
 public ReactiveProperty<string> Input { get; }

Range

数値の範囲。引数に最小値と最大値を設定する。入力値が最小値~最大値の範囲内かどうかをチェックします。

[Range(0,5)]
public ReactiveProperty<string> Input { get; }


型を指定すれば、その型で範囲を指定できます。

[Range(typeof(DateTime),"2020/10/1", "2020/10/5")]
public ReactiveProperty<string> Input { get; }

RegularExpression

正規表現。引数に正規表現のルールを設定する。入力値が正規表現に一致するかチェックしします。

[RegularExpression("[a-d]+")]
public ReactiveProperty<string> Input { get; }

CustomValidation

カスタム検証。引数にクラスの型とクラスが持っているメソッド名を指定する。メソッド内で任意の条件を実装することが可能。

[CustomValidation(typeof(CustomValidateMethods), "Test")]
public ReactiveProperty<string> Input { get; }
CustomValidateMethods.cs
public static class CustomValidateMethods
{

    public static ValidationResult Test(object value, ValidationContext context)
    {
        var input = value?.ToString() ?? string.Empty;
        // 何らかの条件
        var result = input == "123";
        return result ? ValidationResult.Success : new ValidationResult("エラーです。");
    }
}

ValidationAttribute属性を継承

基底クラスのValidationAttributeクラスを継承すると、自前の検証クラスを作ることができます。

[MyValidation("abc","abcって入力してください。")]
public ReactiveProperty<string> Input { get; }
MyValidationAttribute.cs
[AttributeUsage(AttributeTargets.Property)]
public class MyValidationAttribute: ValidationAttribute
{
    public string Answer { get; }

    public MyValidationAttribute(string ansewer, string errorMessage = "")
    {
        this.Answer = ansewer;
        if (!string.IsNullOrEmpty(errorMessage)) this.ErrorMessage = errorMessage;
    }

    protected override ValidationResult IsValid(object value, ValidationContext context)
    {
        var input = value?.ToString() ?? string.Empty;
        // 何らかの条件
        var result = input == this.Answer;
        return result ? ValidationResult.Success : new ValidationResult(this.ErrorMessage);
    }
}

【おまけ】ボタンとの連携

入力値の検証をボタンの活性・非活性を組み合わせることができます。
エラーがなくなるまで、ボタンは押させない!

    public ReactiveCommand Execute { get; }
    this.Execute = new[]
    {
        this.Input.ObserveHasErrors
    }
    .CombineLatestValuesAreAllFalse()
    .ToReactiveCommand()
    .AddTo(this.disposedValue);


最後に

他にもいろいろValidationの属性はあるかと思いますが、とりあえずここまで。

以上。