在MVVM中,我们一般将前台xaml需绑定的变量统一写在ViewModel中,而对于数据的验证,也会在viewModel中进行处理:
这里详解DataAnnotations方法:
首先ViewModel需要引用System.ComponentModel.DataAnnotations,接下来我们需要为viewModel建立viewModelBase类,方便所有viewModel统一处理验证,
base类中可写的东西有很多,这边列出2个我们需要的方法:
public class ViewModelBase : IDataErrorInfo
{
public string this[string columnName]
{
get
{
var validationResults = new List<ValidationResult>();
if (Validator.TryValidateProperty(GetType().GetProperty(columnName).GetValue(this, null),
new ValidationContext(this, null, null) { MemberName = columnName },
validationResults))
{
return null;
}
return validationResults.First().ErrorMessage;
}
}
protected bool IsValid()
{
return Validator.TryValidateObject(
this, new ValidationContext(this, null, null), new List<ValidationResult>(), true);
}
}
这样以后,我们就能在viewModel中进行相关验证了“:
public class SampleViewModel : ViewModelBase
{
public int ID { get; set; }
[Display(Name = "Condition Name")]
[Required(ErrorMessageResourceName = ValidationErrorMessagesResourceNames.Required,
ErrorMessageResourceType = typeof(ValidationErrorMessages))]
[StringLength(30, ErrorMessageResourceName = ValidationErrorMessagesResourceNames.StringMaximumLength,
ErrorMessageResourceType = typeof(ValidationErrorMessages))]
public string Name { get; set; }
}
提示的message可以自定义resource,而DataAnnotations
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter,
AllowMultiple = false)]
public class StringValidate : ValidationAttribute
{
private static readonly Regex InvalidRegex
= new Regex(@"[^a-zA-Z0-9 -/:-@\[-\`\{-\~]");
public StringValidate()
: base(() => "Error string")
{
}
public override bool IsValid(object value)
{
var s = Convert.ToString(value);
if (string.IsNullOrEmpty(s)) return true;
return !InvalidRegex.IsMatch(s);
}
}
最后我们的viewModel就能变成:
public class SampleViewModel : ViewModelBase
{
public int ID { get; set; }
[Display(Name = "Condition Name")]
[Required(ErrorMessageResourceName = ValidationErrorMessagesResourceNames.Required,
ErrorMessageResourceType = typeof(ValidationErrorMessages))]
[StringLength(30, ErrorMessageResourceName = ValidationErrorMessagesResourceNames.StringMaximumLength,
ErrorMessageResourceType = typeof(ValidationErrorMessages))]
[StringValidate]
public string Name { get; set; }
}
即Name只限输入英语,数字,符号,别的全角字符一律不行。
最后,在xmal中定义以下style:
<Style x:Key="TextBoxStyleBase" TargetType="TextBox">
<Style.Triggers>
<!-- Validation エラー時にエラー内容を ToolTip 表示する -->
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip"
Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={RelativeSource Mode=Self}}" />
</Trigger>
</Style.Triggers>
</Style>
这里提示是用tooltip提示,当然还可以用adornedElementPlaceHolder这种旁边的修饰框
<Style x:Key="ValidateTextBoxStyle" TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Left" Background="Red" Foreground="White" FontSize="11" Height="17"
Width="Auto"
VerticalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap" FontFamily="Arial"
Text="{Binding ElementName=ErrorBox, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
</TextBlock>
<AdornedElementPlaceholder Name="ErrorBox" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
最后在binding的时候设置ValidatesOnDataErrors=true就可以了