入力データ検証 その6 カスタムValidationRule

その5ではIDataErrorInfoインターフェイス実装により発生するエラーをチェックするDataErrorValidationRuleをご紹介しました。既定で用意されているValidationRuleはExceptionValidationRuleとDataErrorValidationRuleの2つだけで、これらを使用する場合にはバインドしているソースオブジェクト側に検証ロジックを書くかたちになります。これら2つの方法以外に、ValidationRuleクラスを継承して、カスタムのValidationRuleを作成する方法があります。今回はそれをご紹介します。


ValidationRuleクラスは抽象クラスとなっており、実装が必要なメンバはValidateメソッドです。このメソッドでバインディングによって転送されてくる値を受け取り、検証を行い、その結果をValidationResultとして返します。


Window1.xaml

<Window x:Class="Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local="clr-namespace:ValidationSample"
   Title="Window1" Height="300" Width="300" FontSize="32">
    <Window.Resources>
        <Style TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip"
                          Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
 
    <StackPanel>
 
        <TextBox Margin="30">
            <TextBox.Text>
                <Binding Path="ID">
                    <Binding.ValidationRules>
                        <local:IsPositiveIdValidation/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
 
        <Button Content="Button" Margin="30"/>
 
    </StackPanel>
</Window>


IsPositiveIdValidation.vb
Public Class IsPositiveIdValidation
    Inherits ValidationRule
 
    Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As System.Globalization.CultureInfo) As System.Windows.Controls.ValidationResult
        Dim result As Integer
        If Not Integer.TryParse(CType(value, String), result) Then
            Return New ValidationResult(False, "整数値を入力してください。")
        ElseIf result < 0 Then
            Return New ValidationResult(False, "負の値は入力できません")
        Else
            Return New ValidationResult(True, Nothing)
        End If
    End Function
End Class





今回のようにTextBoxのTextプロパティでバインドしている場合であればValidateメソッドのValueにString型の値が入ってきますが、たとえばSliderのValueでバインドしている場合にはDouble型が入ってくるようになります。作ったValidationRuleはさまざまなところで使われる可能性がありますので、他の型が入ってくることも考慮した実装にしておいたほうが良いかもしれません。


入力データ検証シリーズも6回を迎えましたが、まだ続きます。次回は個々のプロパティ単位ではなくソースオブジェクト全体の検証を行う方法についてご紹介する予定です。