入力データ検証 その5 DataErrorValidationRule
一番初めのその1ではExceptionValidationRuleというValidationRuleを使用しました。これはバインドしているソースオブジェクトから例外がスローされた場合に検証不合格とするルールでした。これ以外に既定で用意されているValidationRuleとして今回はDataErrorValidationRuleをご紹介します。なお、DataErrorValidationRuleクラスは.NET Framework 3.5 SP1、および3.0 SP1から追加されたものです。
DataErrorValidationRuleはソースオブジェクトのIDataErrorInfoインターフェイス実装により発生するエラーをチェックするValidationRuleです。IDataErrorInfoインターフェイスは.NET Framework 1.0の頃から存在しており、WindowsフォームやASP.NETの開発者にも馴染みのあるものです。たとえば、WindowsフォームのErrorProviderコントロールはIDataErrorInfoインターフェイス実装により発生したエラーに対応しています。
まずはいつものようにコードから見ていただこうと思います。
Window1.xaml
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
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>
<DataErrorValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<Button Content="Button" Margin="30"/>
</StackPanel>
</Window>
上記のTextBox部分のBindingは下記のようにBinding.ValidatesOnDataErrorsプロパティをTrueに設定する書き方でも同様になります。
Window1.xaml.vb
Sub New()
' この呼び出しは、Windows フォーム デザイナで必要です。
InitializeComponent()
' InitializeComponent() 呼び出しの後で初期化を追加します。
Me.DataContext = New DataSource()
End Sub
End Class
DataSource.vb
Public Class DataSource
Implements IDataErrorInfo
Dim _id As Integer
Public Property ID() As Integer
Get
ID = _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Public ReadOnly Property [Error]() As String Implements System.ComponentModel.IDataErrorInfo.Error
Get
Throw New NotImplementedException()
End Get
End Property
Default Public ReadOnly Property Item(ByVal columnName As String) As String Implements System.ComponentModel.IDataErrorInfo.Item
Get
Dim result As String = Nothing
If columnName = "ID" Then
If (Me.ID < 0) Then
result = "IDは0以上の整数値を入力してください。"
End If
End If
Return result
End Get
End Property
End Class
XAML部分については前回までに説明してきたことになりますので、特に問題ないかと思います。Buttonはフォーカスを遷移させるだけのために置いてあります。
IDataErrorInfoインターフェイスはErrorプロパティとItemプロパティ(インデクサ)を定義します。Errorプロパティはオブジェクト全体に関しての検証エラーを、Itemプロパティはオブジェクトの各プロパティ関しての検証エラーを返すプロパティです。実際にWPFのDataErrorValidationRuleで使用されるのはItemプロパティだけになります。
DataErrorValidationRuleを使用する方法の場合、検証ロジックはソースオブジェクト側に記述することになります。そのため、通常のバインディングプロセスのように
「ターゲットの変更」→「検証」→「変換」→「ソースへの反映」
ではなく、
「ターゲットの変更」→「変換」→「ソースへの反映」→「検証」
といった順番で最後に検証が行われます。
ソースへ値を反映した後でなければソース側で検証を行う際に値を確認できませんので、これは当然と言えば当然の動作になります。
ちなみにいつ検証を行うのかはValidationRule.ValidationStepプロパティで設定することができます。
Itemプロパティの実装はとても簡単です。インデクサのパラメータとして受けとるプロパティ名を判断して、そのプロパティが検証エラーならばStringでエラー内容を返します。
以上で、DataErrorValidationRuleのご紹介はおしまいです。次回は、カスタムのValidationRuleを作成する方法についてご紹介しようと思います。