先来总结下实现错误提示功能的几个要点
1:binding 的ValidationRules
2 :Validation.ErrorTemplate
首先我们在界面添加一个TextBox, Text绑定到people对象的属性age
public class People
{
public int age { get; set; }
public string name { get; set; }
}
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="30" Margin="75,35,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="155"> <TextBox.Text> <Binding UpdateSourceTrigger="PropertyChanged" Source="{StaticResource people}" Path="age" > <Binding.ValidationRules> <local:AgeValidationRule ></local:AgeValidationRule> </Binding.ValidationRules> </Binding> </TextBox.Text> </TextBox>
这里我们binding.ValidationRules 添加一个自己写的错误验证规则AgeValidationrule 代码如下
public class AgeValidationRule : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { int ret = 0; if(!int.TryParse(value.ToString(),out ret)) return new ValidationResult(false, "不是有效的数字"); if( ret >130 || ret<1) return new ValidationResult(false, "年龄必须是1-130之间"); return new ValidationResult(true, ""); } }
这样,当Text的值变化时,就会触发binding的验证规则,调用到这里面的validate函数。函数的第一个参数value传的是我们绑定的值,第二个是时区信息,这里我们不用管第二个。
此时,我们的TextBox已经有了自我检查的能力。比如输入一个a ,a不是数字,触发validate函数时,验证返回错误信息
ValidationResult(false, "不是有效的数字")
可以看到框框变红了。这是因为使用了TextBox自带默认的errorTemplate.
这样的提示不够明显,还达不到我们的要求
下面我们来自己动手做一个错误提示模板
<Validation.ErrorTemplate> <ControlTemplate> <StackPanel Orientation="Horizontal"> <AdornedElementPlaceholder Name="customAdorner"></AdornedElementPlaceholder> <TextBox Text="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" Margin="10,0,0,0" BorderBrush="Red" Foreground="Red" VerticalContentAlignment="Center" > </TextBox> </StackPanel> </ControlTemplate> </Validation.ErrorTemplate>
分析一下这里的代码,Validation.ErrorTemplate,作为一个附加属性,绑在TextBox上,当TextBox的Text 改变时,触发binding的验证规则 ValidationRules 。会调用到里面对应的validate函数。
如果该函数返回结果为错误。那么这个ErrorTemplate 就会显示出来。
ErrorTemplate 中有一个很有意思的控件 AdornedElementPlaceholder ,它代表了整个ErrorTemplate 的宿主。假设我有一个名为XXX的控件,设置XXX的ErrorTemplate为上面的ErrorTemplate。那么这个AdornedElementPlaceholder 就代表了这个XXX控件。这样,我的ErrorTemplate就可以根据XXX控件的位置,来定位出StackPanel 和ErrorTemplate中textbox的位置。
即定位了我的错误提示内容的位置。
好,我们看到TextBox可以设置自己的附加属性Validation.ErrorTemplate,应该说整个Validation都可以看成TextBox的附加属性。那么这个Validation里还有一些我们能用到的东西。
当Bingding的验证触发后,会把里面的错误信息保存到这个Validation的Errors列表中。这样,我们就可以取出里面的错误信息。即Validate函数返回的年龄必须是1-130之间。
所以,我们把错误提示用的TextBox的Text绑定到它的AdornedElementPlaceholder 对应控件的(Validation.Errors)[0].ErrorContent
Text="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
至此,大功告成
看一下效果
源码路径 : https://files.cnblogs.com/files/CSSZBB/TextBoxErrorHint.zip
原文地址:https://www.cnblogs.com/CSSZBB/p/9372643.html