在现代软件开发中,数据验证是一个不可或缺的环节。它不仅确保了数据的准确性和完整性,还提高了用户体验。FluentValidation是一个流行的.NET库,它提供了一种声明式的方式来定义验证规则。本文将介绍如何在MVVM(Model-View-ViewModel)模式中使用FluentValidation进行数据验证。
FluentValidation简介
FluentValidation是一个开源的.NET库,用于构建验证规则。它支持Lambda表达式,可以避免重复代码。FluentValidation提供了多种内置验证器,如NotNullValidator、NotEmptyValidator、NotEqualValidator等。此外,它还支持自定义逻辑和错误消息。对于XAML应用程序,可以将FluentValidation与IDataErrorInfo接口结合使用,实现更强大的数据验证功能。
安装FluentValidation
要使用FluentValidation,首先需要通过NuGet下载其DLL文件。这可以通过Visual Studio的NuGet包管理器轻松完成。
定义验证规则
在MVVM模式中,验证通常在ViewModel层进行。以下是一个简单的示例,展示了如何使用FluentValidation定义验证规则:
using System;
using FluentValidation;
namespace FluentApplication
{
public class ModelValidator : AbstractValidator
{
public ModelValidator()
{
RuleFor(model => model.ID).NotEmpty();
RuleFor(model => model.ID).Must(IsNumber).WithMessage("This is not a number");
RuleFor(model => model.ID).LessThan(10).WithMessage("ID should be less than 10");
RuleFor(model => model.Name).NotEmpty();
RuleFor(model => model.Name).Length(1, 5);
}
private bool IsNumber(int ID)
{
// 自定义验证逻辑
return true;
}
}
}
在上面的代码中,定义了一个ModelValidator类,它继承自AbstractValidator。为Model的ID和Name属性定义了一些验证规则。这些规则包括NotEmpty、LessThan和Length等内置验证器,以及一个自定义验证器IsNumber。
自定义验证逻辑
自定义验证逻辑可以通过Must方法实现。在上面的示例中,定义了一个IsNumber方法,用于验证ID属性是否为数字。这个方法的输入参数类型与调用属性的类型一致,因此IsNumber方法的输入参数将始终反映传递的属性值。
触发子验证
FluentValidation还支持子验证。例如,如果正在验证Address对象,可以进一步触发Address的内部属性,如邮政编码、街道名称等。
定义Model
在MVVM模式中,Model通常是一个简单的POCO类。以下是一个简单的Model定义:
using FluentValidation.Results;
using System;
using System.ComponentModel;
namespace FluentApplication
{
public class Model : IDataErrorInfo
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Error
{
get;
set;
}
public string this[string columnName]
{
get
{
var validator = new ModelValidator();
if (columnName == "Name")
{
if (validator.Validate(this, columnName).Errors.Any())
return validator.Validate(this, columnName).Errors.FirstOrDefault().ErrorMessage;
else
return string.Empty;
}
if (columnName == "ID")
{
if (validator.Validate(this, columnName).Errors.Any())
return validator.Validate(this, columnName).Errors.FirstOrDefault().ErrorMessage;
else
return string.Empty;
}
return string.Empty;
}
}
}
}
在上面的代码中,实现了IDataErrorInfo接口,这将内部触发FluentValidation。可以根据需要为单个属性或整个模型触发验证。
定义ViewModel
ViewModel是MVVM模式的核心,它负责协调Model和View之间的交互。以下是一个简单的ViewModel定义:
using System.Collections.ObjectModel;
namespace FluentApplication
{
class ViewModel
{
public ViewModel()
{
ModelLists = new ObservableCollection();
ModelLists.Add(new Model() { ID = 1, Name = "Adi" });
ModelLists.Add(new Model() { ID = 2, Name = "Abi" });
}
public ObservableCollection ModelLists { get; set; }
}
}
在上面的代码中,定义了一个ViewModel类,它包含一个Model列表。这个列表被绑定到View中的DataGrid控件。
定义View
View是用户界面层,负责显示数据和接收用户输入。以下是一个简单的View定义:
<Window x:Class="FluentApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid x:Name="dgMain" ItemsSource="{Binding ModelLists,Mode=TwoWay,ValidatesOnDataErrors=True, ValidatesOnNotifyDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False" Margin="22,1,31,161" RenderTransformOrigin="0.5,0.5">
<DataGrid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform AngleY="0.669"/>
<RotateTransform/>
<TranslateTransform Y="1.962"/>
</TransformGroup>
</DataGrid.RenderTransform>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ID,UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name,UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>