表單的數據驗證往往枯燥無味,又不可避免.
在一個如下表單只有兩個輸入框,和確定按鈕的情況下,正常我們需要做哪些工作呢?
1. 如果年齡輸入框輸入了非數字的字符串,輸入框失去焦點后,后面錯誤消息應當能立即提示出來
2.錯誤的提示的內容如果變化,你可能需要修改整個UI設計.(如顯示在輸入框下方)
3.點擊OK按鈕,需要遍歷Window所有輸入框,如果有輸入數據驗證不符合,需要提示錯誤,並將對應的控件獲取焦點.
這很容易么?當這個輸入框再多一些呢?
下面的Demo,看在WPF如何輕松處理這些:
Window里,textBox1,textBox2,textBox3 綁定的數據為:

DataSource
- 使用自定義驗證規則
<TextBox Name="textBox1" Width="50" FontSize="15" Validation.ErrorTemplate="{StaticResource validationTemplate}" Style="{StaticResource textBoxInError}" Grid.Row="1" Grid.Column="1" Margin="2"> <TextBox.Text> <Binding Path="Age" Source="{StaticResource ods}" UpdateSourceTrigger="PropertyChanged" > <Binding.ValidationRules> <c:AgeRangeRule Min="21" Max="130"/> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox>
textBox1 綁定了Age ,並且使用的驗證的規則為 AgeRangeRule ,規則中指定了最小值和最大值,當PropertyChanged時驗證規則將觸發,也就是該控件失去焦點之時. 提示的信息樣式定義在ErrorTemplate里,讓我們再來看一看ErrroTemplate的內容:
<ControlTemplate x:Key="validationTemplate"> <DockPanel> <TextBlock Foreground="Red" FontSize="20">!</TextBlock> <AdornedElementPlaceholder/> </DockPanel> </ControlTemplate>
AdornedElementPlaceholder 才是這里的點睛之處,此處放置了待驗證的控件,而整個ErrorTemplate正是使用神奇的Adoner實現了錯誤的提示的位置和原排版布局的無關性. 驗證規則和整個代碼完全解耦:

rule
<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}"> <Style.Triggers> <Trigger Property="Validation.HasError" Value="true"> <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </Style.Triggers> </Style>
- 使用ExceptionValidationRule
另一種方法,不自定義Rule,如:
<TextBox Name="textBox3" Width="50" FontSize="15" Grid.Row="5" Grid.Column="1" Margin="2" Validation.ErrorTemplate="{StaticResource validationTemplate}" Style="{StaticResource textBoxInError}"> <TextBox.Text> <Binding Path="Age3" Source="{StaticResource ods}" UpdateSourceTrigger="PropertyChanged"> <Binding.ValidationRules> <ExceptionValidationRule/> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox>
在后台代碼中:
BindingExpression myBindingExpression = textBox3.GetBindingExpression(TextBox.TextProperty);
Binding myBinding = myBindingExpression.ParentBinding;
myBinding.UpdateSourceExceptionFilter = new UpdateSourceExceptionFilterCallback(ReturnExceptionHandler);
myBindingExpression.UpdateSource();
因為Age3 是Int類型,在textBox3 輸入非int類型,將會引發異常,此時使用Rule的正是系統的ExceptionValidationRule,同樣錯誤信息的模塊不變.
- 驗證所有控件
在點擊確定可使用該方法再次驗證,在數據不合法的情況下,使用戶無法提交
代碼: 下載